カラムがずれていてUNIONが面倒問題がこれで解決できる(かもしれない)
UNION ALLはめんどうなので何とかしたい
通常のUNION ALLを使うとき、複数のSELECT文のカラム数と順序が完全に一致している必要がある。テーブル数が多いと、カラム名を全部列挙して順序を合わせるのは面倒だ。
なんとかできないものかと以前から思っていたが、FULL UNION ALL CORRESPONDINGなる関数をみつけた。
【アップデート】BigQuery の BY NAME と CORRESPONDING でカラム名ベースの集合演算が可能になりました
いつの間にかに追加されてたみたい。
サンプル
実際にどう動くか見てもらうのが早いだろう。
2つのテーブルがある。テーブルaは1カラム、テーブルbは2カラムなのでUNION ALLはできない。aにカラムyを入れるか、bのカラムyを削ることが必要だ。
しかし、FULL UNION ALL CORRESPONDINGは実行できる。カラムが足りなくても保管してNULLで埋めてくれるし、順番がずれていてもカラム名でUNIONしてくれる。
WITH a AS (
SELECT 1 AS x
),
b AS (
SELECT 3 AS y, 2 AS x
)
SELECT *
FROM a
FULL UNION ALL CORRESPONDING
SELECT *
FROM b
-- 実行結果:
-- x y
-- 1 NULL
-- 2 3
FULL UNION ALL CORRESPONDINGのメリット
- カラムが不足していた場合に自動的に保管してNULLで埋めてくれる
- カラム順序を気にしなくてよい。各SELECT文でカラムの順序が違っていても、カラム名が一致していれば自動的にマッチングされる
- 追加が楽になる。必要なテーブルにだけ追加すればいい
FULL UNION ALL CORRESPONDINGのデメリット
- 今のところBigQuery専用の構文らしい
- カラムがずれていてもエラーが起きない
ぐらいだろうか。メリットに比べるとデメリットはかなり小さい印象だ。
あと、情報がなく本当に正しい挙動なのか保証できない、というのもデメリットかもしれない
その他の細かい注意点
- 同じカラム名でデータ型が違う場合はエラーになる
- 一番上のテーブルに値がない場合、NULLが数値型で埋まるので2番目以降に文字列が入るとエラーになる模様
最初のはUNIONと同じ。2番目は気づかないとはまりそう。最初のテーブルでNULLをstringにCASTするか、文字列がある場合を先頭に持ってくるしかない。
いっそ先頭のテーブルに強制的にCASTするオプションとか作ってほしい。
INNERとLEFTもある
JOINと同じく、INNERとLEFTもある。
INNER UNION ALL CORRESPONDINGなら共通のカラムだけLEFT UNION ALL CORRESPONDINGなら一番最初のテーブルにあるカラムだけ
LEFTはLEFT JOINのイメージなんだろうけど、左というのがかえってわかりづらい気がしなくもない。
両方ともFULLでUNIONしてからカラムで絞り込みする方がいいので、よほど巨大で先に絞り込みしないと無理な状況でなければFULLでいいのでは。
なおRIGHTはないみたい。
もう全部これでいいんじゃないの
いままでさんざん悩まされている問題であり、こんな便利な関数があることになぜ今まで気が付かなかったのか、見つけた時には本当におどろいた。データ整備でUNION使うならもう全部これでいいのでは。
ただ、今ならAIに渡して適度に埋めてもらえば済むことも多い。もう少し早ければ大活躍していたのではと考えると非常に惜しい。