JOIN句
JOIN句は、共通の値を使用して、1つまたは複数のテーブルからのカラムを結合することによって新しいテーブルを生成します。これは、SQLサポートを持つデータベースで一般的な操作であり、関係代数の結合に相当します。1つのテーブルの結合の特別なケースは、しばしば「自己結合」と呼ばれます。
構文
ON句からの式とUSING句からのカラムは「結合キー」と呼ばれます。特に記載されていない限り、JOINは一致する「結合キー」を持つ行からのデカルト積を生成し、これによりソーステーブルよりも多くの行を持つ結果が生成される可能性があります。
サポートされているJOINタイプ
すべての標準SQL JOINタイプがサポートされています。
| タイプ | 説明 |
|---|---|
INNER JOIN | 一致する行のみが返されます。 |
LEFT OUTER JOIN | 一致する行に加えて、左のテーブルからの一致しない行も返されます。 |
RIGHT OUTER JOIN | 一致する行に加えて、右のテーブルからの一致しない行も返されます。 |
FULL OUTER JOIN | 一致する行に加えて、両方のテーブルからの一致しない行も返されます。 |
CROSS JOIN | テーブル全体のデカルト積を生成し、「結合キー」は指定されません。 |
- タイプが指定されていない
JOINはINNERを意味します。 - キーワード
OUTERは安全に省略できます。 CROSS JOINの代替構文は、カンマで区切られた複数のテーブルをFROM句に指定することです。
ClickHouseで利用可能な追加の結合タイプは次の通りです:
| タイプ | 説明 |
|---|---|
LEFT SEMI JOIN, RIGHT SEMI JOIN | 「結合キー」における許可リスト、デカルト積を生成しません。 |
LEFT ANTI JOIN, RIGHT ANTI JOIN | 「結合キー」における拒否リスト、デカルト積を生成しません。 |
LEFT ANY JOIN, RIGHT ANY JOIN, INNER ANY JOIN | パーシャル(LEFTとRIGHTの対向側用)または完全(INNERとFULL用)にデカルト積を無効にします。 |
ASOF JOIN, LEFT ASOF JOIN | 非正確な一致でシーケンスを結合します。ASOF JOINの使用法は以下で説明します。 |
PASTE JOIN | 2つのテーブルの水平連結を行います。 |
join_algorithmがpartial_mergeに設定されている場合、RIGHT JOIN及びFULL JOINはALLの厳密性でのみサポートされます(SEMI, ANTI, ANY, ASOFはサポートされていません)。
設定
デフォルトの結合タイプは、join_default_strictness設定を使用してオーバーライドできます。
ANY JOIN操作に対するClickHouseサーバーの動作は、any_join_distinct_right_table_keys設定に依存します。
参照:
join_algorithmjoin_any_take_last_rowjoin_use_nullspartial_merge_join_rows_in_right_blocksjoin_on_disk_max_files_to_mergeany_join_distinct_right_table_keys
cross_to_inner_join_rewrite設定を使用して、ClickHouseがCROSS JOINをINNER JOINとして書き換えられなかった場合の動作を定義します。デフォルト値は1で、結合を続行できますが、遅くなります。cross_to_inner_join_rewriteを0に設定するとエラーがスローされ、2に設定するとクロス結合を実行せず、すべてのカンマ/クロス結合の書き換えを強制します。値が2のときに書き換えが失敗した場合、「WHEREセクションを簡素化してみてください」とのエラーメッセージが表示されます。
ONセクションの条件
ONセクションには、ANDやOR演算子を使用して結合された複数の条件を含めることができます。結合キーを指定する条件は次のようにする必要があります:
- 左テーブルと右テーブルの両方を参照する
- 等号演算子を使用する
他の条件は他の論理演算子を使用できますが、クエリの左または右テーブルのいずれかを参照する必要があります。
行は、複雑な条件全体が満たされた場合に結合されます。条件が満たされない場合、JOINタイプに応じて結果に行が含まれることがあります。同じ条件がWHEREセクションに置かれ、それが満たされない場合、行は結果から必ずフィルタリングされます。
ON句内のOR演算子はハッシュ結合アルゴリズムを使用して機能します。JOINの結合キーを持つ各OR引数ごとに別々のハッシュテーブルが作成されるため、メモリ消費量とクエリ実行時間はON句のOR式の数の増加に対して線形に増加します。
異なるテーブルのカラムを参照する条件については、現在のところ等号演算子(=)のみがサポートされています。
例
table_1とtable_2を考えます:
1つの結合キー条件とtable_2の追加条件を持つクエリ:
結果には、名前がCでテキストのカラムが空の行が含まれていることに注意してください。これはOUTERタイプの結合が使用されているため、結果に含まれます。
INNERタイプの結合と複数の条件を持つクエリ:
結果:
INNERタイプの結合とORを持つ条件のクエリ:
結果:
INNERタイプの結合とORおよびANDを含む条件のクエリ:
デフォルトでは、同じテーブルからのカラムを使用する限り、不等号条件がサポートされます。
たとえば、t1.a = t2.key AND t1.b > 0 AND t2.b > t2.cのような条件で、t1.b > 0はt1からのカラムのみを使用し、t2.b > t2.cはt2からのカラムのみを使用します。しかし、t1.a = t2.key AND t1.b > t2.keyのような条件の実験的サポートを試してみることができます。詳細は以下のセクションを参照してください。
結果:
異なるテーブルのカラムに対する不等号条件を持つJOIN
Clickhouseは現在、ALL/ANY/SEMI/ANTI INNER/LEFT/RIGHT/FULL JOINを不等号条件と共にサポートしています。これらの不等号条件は、hashおよびgrace_hash結合アルゴリズムでのみサポートされています。不等号条件はjoin_use_nullsではサポートされていません。
例
テーブルt1:
テーブルt2
JOINキーのNULL値
NULLはどの値とも等しくなく、自己を含みます。これは、1つのテーブルのJOINキーにNULL値がある場合、他のテーブルのNULL値と一致しないことを意味します。
例
テーブルA:
テーブルB:
JOINキーのNULL値のために、AテーブルのCharlie行とBテーブルのスコア88の行が結果に含まれていないことに注意してください。
NULL値を一致させたい場合は、isNotDistinctFrom関数を使用してJOINキーを比較します。
ASOF JOIN使用法
ASOF JOINは、正確な一致がないレコードを結合する必要がある場合に便利です。
このJOINアルゴリズムは、テーブルに特別なカラムを必要とします。このカラム:
- 順序付きのシーケンスを含む必要があります。
- 次のいずれかの型である必要があります:Int, UInt、Float、Date、DateTime、Decimal。
hash結合アルゴリズムのためには、JOIN句の唯一のカラムであってはいけません。
構文 ASOF JOIN ... ON:
任意の数の等号条件と正確に1つの最も近い一致条件を使用できます。たとえば、SELECT count() FROM table_1 ASOF LEFT JOIN table_2 ON table_1.a == table_2.b AND table_2.t <= table_1.t。
最も近い一致に対してサポートされている条件:>、>=、<、<=。
構文 ASOF JOIN ... USING:
ASOF JOINはequi_columnXを等号での結合に使用し、asof_columnを最も近い一致での結合に使用します。この条件はtable_1.asof_column >= table_2.asof_columnです。asof_columnカラムは常にUSING句の最後のカラムです。
次のテーブルを考えます:
ASOF JOINはtable_1のユーザーイベントのタイムスタンプを取得し、table_2でtable_1のイベントのタイムスタンプに最も近いイベントを見つけることができます。等しいタイムスタンプ値は、利用可能な場合は最も近いものです。ここで、user_idカラムは等号による結合に使用され、ev_timeカラムは最も近い一致による結合に使用されます。上記の例では、event_1_1はevent_2_1と結合でき、event_1_2はevent_2_3と結合できますが、event_2_2は結合できません。
ASOF JOINはhashおよびfull_sorting_merge結合アルゴリズムによってのみサポートされます。
Joinテーブルエンジンではサポートされていません。
PASTE JOIN使用法
PASTE JOINの結果は、左のサブクエリからのすべてのカラムの後に右のサブクエリからのすべてのカラムが続くテーブルです。
行は、元のテーブルにおける位置に基づいて一致します(行の順序は定義されるべきです)。
サブクエリが異なる数の行を返す場合、余分な行はカットされます。
例:
注意:この場合、読み込みが並行していると結果が非決定論的である可能性があります。たとえば:
分散JOIN
分散テーブルを含むJOINを実行する方法は2つあります:
- 通常の
JOINを使用する場合、クエリはリモートサーバーに送信されます。サブクエリはそれぞれのサーバー上で実行され、正しいテーブルを作成し、そのテーブルで結合が実行されます。言い換えれば、正しいテーブルはそれぞれのサーバーで別々に形成されます。 GLOBAL ... JOINを使用すると、まずリクエスタサーバーがサブクエリを実行して正しいテーブルを計算します。この一時テーブルは各リモートサーバーに渡され、転送された一時データを使用してその上でクエリが実行されます。
GLOBALを使用する際は注意してください。詳細については分散サブクエリセクションを参照してください。
暗黙の型変換
INNER JOIN、LEFT JOIN、RIGHT JOIN、およびFULL JOINクエリは「結合キー」の暗黙の型変換をサポートします。ただし、左テーブルと右テーブルの結合キーが単一の型に変換できない場合(たとえば、UInt64とInt64、またはStringとInt32の両方の値を保持できるデータ型が存在しない場合)、クエリは実行できません。
例
テーブルt_1を考えます:
およびテーブルt_2:
クエリ
はセットを返します:
使用推奨
空またはNULLセルの処理
テーブルを結合する際、空のセルが現れることがあります。join_use_nulls設定は、ClickHouseがこれらのセルをどのように埋めるかを定義します。
JOINキーがNullableフィールドである場合、少なくとも1つのキーに値NULLがある行は結合されません。
構文
USINGに指定されたカラムは、両方のサブクエリで同じ名前を持っている必要があり、他のカラムは異なる名前である必要があります。サブクエリ内のカラムの名前を変更するためにエイリアスを使用できます。
USING句は、これらのカラムの等号を確立するために結合する1つ以上のカラムを指定します。カラムのリストは括弧なしで設定されます。より複雑な結合条件はサポートされません。
構文制限
単一のSELECTクエリ内の複数のJOIN句に対して:
- テーブルが結合されている場合にのみ、
*を使用してすべてのカラムを取得できますが、サブクエリには適用できません。 PREWHERE句は使用できません。USING句は使用できません。
ON、WHERE、およびGROUP BY句に関して:
ON、WHERE、およびGROUP BY句に任意の式を使用することはできませんが、SELECT句で式を定義し、その後これらの句でエイリアスを介して使用することが可能です。
パフォーマンス
JOINを実行する際、クエリの他のステージに関連する実行順序の最適化は行われません。結合(右テーブル内の検索)は、WHEREでのフィルタリングの前および集約の前に実行されます。
同じJOINでクエリが実行されるたびに、結果がキャッシュされないためサブクエリが再度実行されます。これを避けるために、常にRAM内に存在する結合用の準備された配列である特別なJoinテーブルエンジンを使用してください。
場合によっては、JOINの代わりにINを使用する方が効率的です。
次元テーブル(広告キャンペーンの名前などの次元プロパティを含む比較的小さなテーブル)との結合用にJOINが必要な場合、JOINは便利ではないかもしれません。右テーブルが各クエリに対して再アクセスされるためです。そのような場合には、JOINの代わりに使用すべき「辞書」機能があります。詳細についてはDictionariesセクションを参照してください。
メモリ制限
デフォルトでは、ClickHouseはハッシュ結合アルゴリズムを使用します。ClickHouseはright_tableを取り、それに対するハッシュテーブルをRAM内に作成します。join_algorithm = 'auto'が有効になっている場合、メモリ消費のしきい値を超えると、ClickHouseはマージ結合アルゴリズムにフォールバックします。JOINアルゴリズムの説明についてはjoin_algorithm設定を参照してください。
JOIN操作のメモリ消費を制限する必要がある場合、以下の設定を使用します:
- max_rows_in_join — ハッシュテーブル内の行数を制限します。
- max_bytes_in_join — ハッシュテーブルのサイズを制限します。
これらの制限のいずれかに達した場合、ClickHouseはjoin_overflow_mode設定で指示されたように動作します。
例
例:
関連コンテンツ
- ブログ:ClickHouse: A Blazingly Fast DBMS with Full SQL Join Support - Part 1
- ブログ:ClickHouse: A Blazingly Fast DBMS with Full SQL Join Support - Under the Hood - Part 2
- ブログ:ClickHouse: A Blazingly Fast DBMS with Full SQL Join Support - Under the Hood - Part 3
- ブログ:ClickHouse: A Blazingly Fast DBMS with Full SQL Join Support - Under the Hood - Part 4