ClickHouse/docs/ja/sql-reference/statements/select/array-join.md
2024-11-18 11:58:58 +09:00

12 KiB
Raw Blame History

slug sidebar_label
/ja/sql-reference/statements/select/array-join ARRAY JOIN

ARRAY JOIN 句

ARRAY JOIN句は、配列カラムを含むテーブルに対して、そのカラムの各配列要素を持つ新しいテーブルを生成し、他のカラムの値を複製する一般的な操作です。これは、ARRAY JOIN句が行う基本的な内容です。

名前の由来は、配列またはネストされたデータ構造とのJOINの実行として見ることができることにあります。この目的は、arrayJoin 関数と似ていますが、句の機能はより広範です。

構文:

SELECT <expr_list>
FROM <left_subquery>
[LEFT] ARRAY JOIN <array>
[WHERE|PREWHERE <expr>]
...

SELECT クエリでは、ARRAY JOIN 句を1つだけ指定できます。

サポートされているARRAY JOINのタイプは以下の通りです:

  • ARRAY JOIN - 基本の場合、空の配列は JOIN の結果に含まれません。
  • LEFT ARRAY JOIN - JOIN の結果に空の配列を持つ行が含まれます。空の配列の値は、配列要素タイプのデフォルト値通常は0、空文字列、または NULLに設定されます。

基本的な ARRAY JOIN の例

以下の例では、ARRAY JOIN および LEFT ARRAY JOIN の使用法を示します。Array タイプのカラムを持つテーブルを作成し、値を挿入します:

CREATE TABLE arrays_test
(
    s String,
    arr Array(UInt8)
) ENGINE = Memory;

INSERT INTO arrays_test
VALUES ('Hello', [1,2]), ('World', [3,4,5]), ('Goodbye', []);
┌─s───────────┬─arr─────┐
│ Hello       │ [1,2]   │
│ World       │ [3,4,5] │
│ Goodbye     │ []      │
└─────────────┴─────────┘

以下の例は、ARRAY JOIN 句を使用します:

SELECT s, arr
FROM arrays_test
ARRAY JOIN arr;
┌─s─────┬─arr─┐
│ Hello │   1 │
│ Hello │   2 │
│ World │   3 │
│ World │   4 │
│ World │   5 │
└───────┴─────┘

次の例は、LEFT ARRAY JOIN 句を使用します:

SELECT s, arr
FROM arrays_test
LEFT ARRAY JOIN arr;
┌─s───────────┬─arr─┐
│ Hello       │   1 │
│ Hello       │   2 │
│ World       │   3 │
│ World       │   4 │
│ World       │   5 │
│ Goodbye     │   0 │
└─────────────┴─────┘

エイリアスの使用

ARRAY JOIN 句で配列のエイリアスを指定できます。この場合、配列項目にはこのエイリアスでアクセスできますが、配列自体には元の名前でアクセスします。例:

SELECT s, arr, a
FROM arrays_test
ARRAY JOIN arr AS a;
┌─s─────┬─arr─────┬─a─┐
│ Hello │ [1,2]   │ 1 │
│ Hello │ [1,2]   │ 2 │
│ World │ [3,4,5] │ 3 │
│ World │ [3,4,5] │ 4 │
│ World │ [3,4,5] │ 5 │
└───────┴─────────┴───┘

エイリアスを使用して、外部配列とのARRAY JOINを実行できます。例:

SELECT s, arr_external
FROM arrays_test
ARRAY JOIN [1, 2, 3] AS arr_external;
┌─s───────────┬─arr_external─┐
│ Hello       │            1 │
│ Hello       │            2 │
│ Hello       │            3 │
│ World       │            1 │
│ World       │            2 │
│ World       │            3 │
│ Goodbye     │            1 │
│ Goodbye     │            2 │
│ Goodbye     │            3 │
└─────────────┴──────────────┘

複数の配列は、ARRAY JOIN句でカンマで区切ることができます。この場合、JOINは同時に実行されます(直和であり、直積ではありません)。デフォルトでは、すべての配列は同じサイズである必要があります。例:

SELECT s, arr, a, num, mapped
FROM arrays_test
ARRAY JOIN arr AS a, arrayEnumerate(arr) AS num, arrayMap(x -> x + 1, arr) AS mapped;
┌─s─────┬─arr─────┬─a─┬─num─┬─mapped─┐
│ Hello │ [1,2]   │ 1 │   1 │      2 │
│ Hello │ [1,2]   │ 2 │   2 │      3 │
│ World │ [3,4,5] │ 3 │   1 │      4 │
│ World │ [3,4,5] │ 4 │   2 │      5 │
│ World │ [3,4,5] │ 5 │   3 │      6 │
└───────┴─────────┴───┴─────┴────────┘

以下の例では、arrayEnumerate関数を使用しています:

SELECT s, arr, a, num, arrayEnumerate(arr)
FROM arrays_test
ARRAY JOIN arr AS a, arrayEnumerate(arr) AS num;
┌─s─────┬─arr─────┬─a─┬─num─┬─arrayEnumerate(arr)─┐
│ Hello │ [1,2]   │ 1 │   1 │ [1,2]               │
│ Hello │ [1,2]   │ 2 │   2 │ [1,2]               │
│ World │ [3,4,5] │ 3 │   1 │ [1,2,3]             │
│ World │ [3,4,5] │ 4 │   2 │ [1,2,3]             │
│ World │ [3,4,5] │ 5 │   3 │ [1,2,3]             │
└───────┴─────────┴───┴─────┴─────────────────────┘

異なるサイズの複数の配列は次のようにして結合できます: SETTINGS enable_unaligned_array_join = 1。例:

SELECT s, arr, a, b
FROM arrays_test ARRAY JOIN arr as a, [['a','b'],['c']] as b
SETTINGS enable_unaligned_array_join = 1;
┌─s───────┬─arr─────┬─a─┬─b─────────┐
│ Hello   │ [1,2]   │ 1 │ ['a','b'] │
│ Hello   │ [1,2]   │ 2 │ ['c']     │
│ World   │ [3,4,5] │ 3 │ ['a','b'] │
│ World   │ [3,4,5] │ 4 │ ['c']     │
│ World   │ [3,4,5] │ 5 │ []        │
│ Goodbye │ []      │ 0 │ ['a','b'] │
│ Goodbye │ []      │ 0 │ ['c']     │
└─────────┴─────────┴───┴───────────┘

ネストされたデータ構造との ARRAY JOIN

ARRAY JOINネストされたデータ構造にも対応しています:

CREATE TABLE nested_test
(
    s String,
    nest Nested(
    x UInt8,
    y UInt32)
) ENGINE = Memory;

INSERT INTO nested_test
VALUES ('Hello', [1,2], [10,20]), ('World', [3,4,5], [30,40,50]), ('Goodbye', [], []);
┌─s───────┬─nest.x──┬─nest.y─────┐
│ Hello   │ [1,2]   │ [10,20]    │
│ World   │ [3,4,5] │ [30,40,50] │
│ Goodbye │ []      │ []         │
└─────────┴─────────┴────────────┘
SELECT s, `nest.x`, `nest.y`
FROM nested_test
ARRAY JOIN nest;
┌─s─────┬─nest.x─┬─nest.y─┐
│ Hello │      1 │     10 │
│ Hello │      2 │     20 │
│ World │      3 │     30 │
│ World │      4 │     40 │
│ World │      5 │     50 │
└───────┴────────┴────────┘

ARRAY JOIN でネストされたデータ構造の名前を指定する場合、その意味はそれを構成するすべての配列要素に対する ARRAY JOIN と同じです。以下に例を示します:

SELECT s, `nest.x`, `nest.y`
FROM nested_test
ARRAY JOIN `nest.x`, `nest.y`;
┌─s─────┬─nest.x─┬─nest.y─┐
│ Hello │      1 │     10 │
│ Hello │      2 │     20 │
│ World │      3 │     30 │
│ World │      4 │     40 │
│ World │      5 │     50 │
└───────┴────────┴────────┘

以下のバリエーションも意味があります:

SELECT s, `nest.x`, `nest.y`
FROM nested_test
ARRAY JOIN `nest.x`;
┌─s─────┬─nest.x─┬─nest.y─────┐
│ Hello │      1 │ [10,20]    │
│ Hello │      2 │ [10,20]    │
│ World │      3 │ [30,40,50] │
│ World │      4 │ [30,40,50] │
│ World │      5 │ [30,40,50] │
└───────┴────────┴────────────┘

エイリアスをネストされたデータ構造に使用して、JOIN結果またはソース配列を選択することもできます。例:

SELECT s, `n.x`, `n.y`, `nest.x`, `nest.y`
FROM nested_test
ARRAY JOIN nest AS n;
┌─s─────┬─n.x─┬─n.y─┬─nest.x──┬─nest.y─────┐
│ Hello │   1 │  10 │ [1,2]   │ [10,20]    │
│ Hello │   2 │  20 │ [1,2]   │ [10,20]    │
│ World │   3 │  30 │ [3,4,5] │ [30,40,50] │
│ World │   4 │  40 │ [3,4,5] │ [30,40,50] │
│ World │   5 │  50 │ [3,4,5] │ [30,40,50] │
└───────┴─────┴─────┴─────────┴────────────┘

arrayEnumerate関数を使用する例:

SELECT s, `n.x`, `n.y`, `nest.x`, `nest.y`, num
FROM nested_test
ARRAY JOIN nest AS n, arrayEnumerate(`nest.x`) AS num;
┌─s─────┬─n.x─┬─n.y─┬─nest.x──┬─nest.y─────┬─num─┐
│ Hello │   1 │  10 │ [1,2]   │ [10,20]    │   1 │
│ Hello │   2 │  20 │ [1,2]   │ [10,20]    │   2 │
│ World │   3 │  30 │ [3,4,5] │ [30,40,50] │   1 │
│ World │   4 │  40 │ [3,4,5] │ [30,40,50] │   2 │
│ World │   5 │  50 │ [3,4,5] │ [30,40,50] │   3 │
└───────┴─────┴─────┴─────────┴────────────┴─────┘

実装の詳細

クエリ実行の順序は、ARRAY JOIN 実行時に最適化されます。ARRAY JOIN はクエリ内で常に WHERE/PREWHERE 句の前に指定する必要がありますが、ARRAY JOIN の結果がフィルタリングに使用されない限り、技術的には任意の順序で実行できます。処理の順序はクエリオプティマイザによって制御されます。

短絡評価関数との互換性がない

短絡評価関数 は、ifmultiIfandor などの特定の関数で複雑な式の実行を最適化する機能で、ゼロ除算などの潜在的な例外がこれらの関数の実行中に発生するのを防ぎます。

arrayJoin は常に実行され、短絡評価関数には対応していません。これは、すべての他の関数とは異なり、クエリ分析および実行中に別途処理され、arrayJoin の結果に依存して結果の行数が決まるためです。そのため、arrayJoin の遅延評価の実装は複雑で高コストとなります。

関連コンテンツ