ARRAY JOIN句
配列カラムを含むテーブルに対して一般的な操作は、新しいテーブルを生成し、そのテーブルには最初のカラムの各個別の配列要素ごとに行があり、他のカラムの値は重複します。これがARRAY JOIN
句の基本的な動作です。
その名前は、配列またはネストされたデータ構造に対してJOIN
を実行することとして見ることができることから来ています。意図は arrayJoin 関数に似ていますが、句の機能はより広範です。
構文:
サポートされているARRAY JOIN
のタイプは以下の通りです。
ARRAY JOIN
- 基本ケースでは、空の配列はJOIN
の結果に含まれません。LEFT ARRAY JOIN
-JOIN
の結果には空の配列を持つ行が含まれます。空の配列の値は、配列要素の型のデフォルト値(通常は0、空文字列、またはNULL)に設定されます。
基本ARRAY JOINの例
ARRAY JOINおよびLEFT ARRAY JOIN
以下の例は、ARRAY JOIN
およびLEFT ARRAY JOIN
句の使用法を示しています。Array型カラムを持つテーブルを作成し、値を挿入しましょう:
以下の例は、ARRAY JOIN
句を使用しています:
次の例は、LEFT ARRAY JOIN
句を使用しています:
ARRAY JOINおよびarrayEnumerate関数
この関数は通常ARRAY JOIN
とともに使用されます。ARRAY JOIN
を適用した後、各配列の数を一度だけカウントすることを可能にします。例:
この例では、Reachesはコンバージョンの数(ARRAY JOIN
が適用された後に受信された文字列)、Hitsはページビューの数(ARRAY JOIN
の前の文字列)です。この特定のケースでは、より簡単な方法で同じ結果を得ることができます:
ARRAY JOINおよびarrayEnumerateUniq
この関数は、ARRAY JOIN
を使用して配列要素を集約する際に役立ちます。
この例では、各目標IDごとのコンバージョンの数(Goalsのネストデータ構造内の各要素は到達された目標であり、これをコンバージョンと呼びます)とセッションの数を計算しています。ARRAY JOIN
なしでは、セッションの数はsum(Sign)としてカウントされます。しかし、この特定のケースでは、行がネストされたGoals構造によって乗算されているため、これを行った後に各セッションを一度だけカウントするために、arrayEnumerateUniq(Goals.ID)
関数の値に条件を適用します。
エイリアスの使用
ARRAY JOIN
句で配列のエイリアスを指定することができます。この場合、配列アイテムにはこのエイリアスを介してアクセスできますが、配列自体は元の名前でアクセスされます。例:
エイリアスを使用すると、外部配列とのARRAY JOIN
を行うことができます。例えば:
ARRAY JOIN
句では、複数の配列をカンマで区切って指定できます。この場合、同時にJOIN
が行われます(直接的な和であり、直積ではありません)。デフォルトでは、すべての配列は同じサイズである必要があります。例:
以下の例では、arrayEnumerate関数を使用しています:
異なるサイズの複数の配列を結合するには、SETTINGS enable_unaligned_array_join = 1
を使用します。例:
ネストデータ構造を持つARRAY JOIN
ARRAY JOIN
は、ネストされたデータ構造でも機能します:
ARRAY JOIN
でネストデータ構造の名前を指定する際、その意味はそれが構成するすべての配列要素を持つARRAY JOIN
と同じです。以下の例が挙げられます:
このバリエーションも意味があります:
ネストデータ構造にエイリアスを使用することで、JOIN
の結果または元の配列のいずれかを選択できます。例:
arrayEnumerate 関数を使用した例:
実装の詳細
クエリの実行順序は、ARRAY JOIN
を実行する際に最適化されます。ARRAY JOIN
は常にWHERE/PREWHERE句の前に指定しなければなりませんが、技術的にはARRAY JOIN
の結果がフィルタリングに使用されない限り、どの順序でも実行できます。処理の順序はクエリオプティマイザによって制御されます。
短絡評価との互換性の無さ
短絡関数評価は、if
、multiIf
、and
、or
などの特定の関数における複雑な式の実行を最適化する機能です。これは、これらの関数の実行中にゼロ除算などの潜在的な例外が発生するのを防ぎます。
arrayJoin
は常に実行され、短絡関数評価に対応していません。これは、クエリの解析と実行中にすべての他の関数とは別に処理される特異な関数であり、短絡関数実行に対して機能する追加のロジックを必要とするためです。理由は、結果の行数がarrayJoinの結果に依存し、arrayJoin
を遅延実行することは非常に複雑でコストがかかるからです。