🥧
BigQueryでもSnowflakeのARRAY_UNION_AGGのような出力を再現してみる
はじめに
SnowflakeのARRAY_UNION_AGGを使うと配列データのUNIONが簡単にできて便利ですよね。
例えば下記のような感じです。
/* Snowflake */
WITH
sample_data AS (
SELECT 1 AS group_id, [1, 2, 3] AS items
UNION ALL
SELECT 1 AS group_id, [3, 4] AS items
UNION ALL
SELECT 2 AS group_id, [5, 6] AS items
UNION ALL
SELECT 2 AS group_id, [6, 7, 8] AS items
),
union_group_id AS (
SELECT
group_id,
ARRAY_UNION_AGG(items) AS union_items
FROM sample_data
GROUP BY group_id
),
final as (
SELECT
group_id,
union_items
FROM union_group_id
)
SELECT * FROM final;
/*
RESULT
GROUP_ID,UNION_ITEMS
1,[1,2,3,4]
2,[5,6,7,8]
*/
ですが、BigQueryではARRAY_UNION_AGG
関数がありません。
なので、今回は似たような処理をBigQueryで作成していきます。
BigQueryバージョン
/* BigQuery */
WITH
sample_data AS (
SELECT 1 AS group_id, [1, 2, 3] AS items
UNION ALL
SELECT 1 AS group_id, [3, 4] AS items
UNION ALL
SELECT 2 AS group_id, [5, 6] AS items
UNION ALL
SELECT 2 AS group_id, [6, 7, 8] AS items
),
concat_array_group_id AS (
SELECT
group_id,
ARRAY_CONCAT_AGG(items) AS concat_items
FROM sample_data
GROUP BY group_id
),
union_array AS (
SELECT
group_id,
ARRAY(
SELECT DISTINCT unnest_items FROM UNNEST(concat_items) AS unnest_items
) AS union_items
FROM concat_array_group_id
),
final as (
SELECT
group_id,
union_items
FROM union_array
)
SELECT * FROM final;
/*
RESULT
group_id,union_items
1,[1,2,3,4]
2,[5,6,7,8]
*/
各CTEの説明
ダミーデータの準備
WITH
sample_data AS (
SELECT 1 AS group_id, [1, 2, 3] AS items
UNION ALL
SELECT 1 AS group_id, [3, 4] AS items
UNION ALL
SELECT 2 AS group_id, [5, 6] AS items
UNION ALL
SELECT 2 AS group_id, [6, 7, 8] AS items
),
Snowflakeだと、UNION
は重複排除が入っています。
なので、BigQueryで実現するなら UNION DISTINCT
となるはずなのですが、
ARRAY
がUNION DISTINCT
に対応していないのでUNION ALL
にしています。
BQにおけるARRAY_UNION_AGGと似た出力の実現方法
concat_array_group_id AS (
SELECT
group_id,
ARRAY_CONCAT_AGG(items) AS concat_items
FROM sample_data
GROUP BY group_id
),
union_array AS (
SELECT
group_id,
ARRAY(
SELECT DISTINCT unnest_items FROM UNNEST(concat_items) AS unnest_items
) AS union_items
FROM concat_array_group_id
),
ARRAY_UNION_AGG
を二段階の処理に分けて処理しています。
-
concat_array_group_id
のCTE:ARRAY_CONCAT_AGG
で配列をまとめる -
union_array
のCTE:ARRAYの要素をUNNESTで1行にして重複削除し、配列に戻している
追記
SnowflakeのARRAY_UNION_AGG
で使用されている例では構造体を保持することが可能ですが、
BigQueryではその実装までできませんでした・・・
この記事ではgroup byをした際に配列内で重複する内容を消すことのみ可能です。
さいごに
複数のDWHをみてSQLや関数を比較していると
- 実装されてなかったり
- 使い方は同じはずだけど、、出力がちょっと違う・・・
みたいな部分で悩まされますよね〜
あと、意外とBQは配列関連で怒られることが多かったので注意して書かないと理論的には合ってても動かないことがありますね汗
(「ARRAYで二重配列のレコードを持てない」とか「ARRAYに対してUNION DISTINCTができない」とかむつかしい。。。)
何はともあれ、無事にSnowflakeのARRAY_UNION_AGG
と同じような実装をBigQueryできました!
試したい方はぜひ動かしてみてください。
以上hamaでした〜
Discussion