BigQueryのSQLいろいろ (4) ARRAY型・STRUCT型 | Wantedly Engineer Blog
BigQueryのSQLについて、ドキュメントを読んだり実験したりしながら挙動を解き明かしていこうと思います。第4回はARRAYとSTRUCTについて紹介します。今回扱う型ARRAYSTRUCT...
https://www.wantedly.com/companies/wantedly/post_articles/1020507
Photo by Kier in Sight Archives on Unsplash
BigQueryのSQLについて、ドキュメントを読んだり実験したりしながら挙動を解き明かしていこうと思います。第5回はNULLについて紹介します。ここまでで扱わなかったその他の型についても触れます。
NULL値はSQLではおなじみの値です。BigQueryでは、全ての型に出現の余地があります。
テーブルではNULLの保存に制約があります。
NULLに期待される意味は、それが使われる文脈によってまちまちです。
ただし、ほとんどの場面ではNULLは伝播されるため、NULLを (Haskellにおける Maybe Monad のような) 例外の一種とみなすのが実際の挙動に近いといえるかもしれません。
NULLが伝播されない場面としては以下があります。
このうち、 AND/OR の振舞いは注目に値します。実は、NULL を ⊥ と考えたとき、SQLのORの演算表は "por" (parallel or) と呼ばれる演算と一致します。言い換えると、これは双方向にショートサーキットする能力を持っています。
NULL の比較は特殊です。以下のようなケースでは、 NULL 同士は互いに異なるものとして扱われます。
いっぽう、以下のような場合は NULL 同士は互いに同じものとして扱われます。
また、 ORDER BY における NULL の順序は指定により異なります。
BigQuery には NULL 型が存在します。 (NULL 値とは別です)
他の型とそろえる形で言い換えるのであれば、これは「NULLABLE NEVER 型」と呼んだほうが正確かもしれません。
NULL 型をもつ式には以下のものがあります。
NULL は実質的に型推論のための型といえます。そこで、ここではBigQueryの型推論について、実際の挙動から推定した内容を説明します。
まず基本的に、 BigQuery の型推論はボトムアップです。つまり、ある式の型を決定するにあたって、その式の外の式の推論結果を使うことは基本的にありません。
たとえば、以下の SELECT は Hindley-Milner 型の型推論では通る可能性がありますが、 BigQuery では通りません。これは BigQuery の型推論が Hindley-Milner 型の高度な推論ではなく、シンプルなボトムアップ型の推論であることを示唆しています。
SELECT ['foo']
UNION ALL
-- NULL は STRING 型になりそうだが、この部分だけ見ても推論できない
SELECT [NULL]この性質から、 NULL や ERROR(...) のように制約されていないジェネリクスを持つ式はそのままではBigQueryの枠組みで表現できないことになります。
いっぽう、以下の場合は型が通ります。
-- OK
SELECT NULL
UNION ALL
SELECT 'foo'
-- OK
SELECT ['foo']
UNION ALL
SELECT [NULL, 'bar']このとき、型がわかっている側の式と、型が不明な側の式の順序は問いません。
このことから、 NULL や ERROR(...) などの式は型強制によって適切な型に変換されていると推定されます。そのための中継地点となる型が NULL ということになります。
まとめると、
となります。
一部の式では、NULL 型から INT64 へのフォールバックが発生します。
このことは以下のようなクエリで確認できます。
SELECT [NULL] || ['foo'] -- エラー
SELECT [NULL] || [42] -- OKまた、 TYPEOF もこのような振舞いをするため、 TYPEOF で NULL 型を直接観測することはできません。
SELECT TYPEOF(NULL) -- 'INT64'
SELECT TYPEOF(ERROR('foo')) -- 'INT64'主要なジェネリックな式について振舞いをまとめると、以下のようになります。
なお、 UNION ALL が INT64 へのフォールバックを持つことから、以下のように結合性が成立しません。
-- エラー (最初の UNION ALL で INT64 になってしまう)
(
SELECT NULL
UNION ALL
SELECT NULL
)
UNION ALL
SELECT 'foo'
-- OK (1回の UNION ALL でまとめて型強制されるので、まとめて STRING になる)
SELECT NULL
UNION ALL
SELECT NULL
UNION ALL
SELECT 'foo'型検査エラーとは別に、 NULL リテラルの出現が禁止されている場所があります。
これらは構文的に NULL に一致するものを弾くルールなので、たとえば NULL のかわりに COALESCE(NULL) と書けば通ります。
BOOLEAN 型はきわめてシンプルで、以下の3つの値を持ちます。
BOOLEAN 専用の演算子として、 AND/OR/NOT の他に以下のものが特筆に値します。
他には特筆すべき特徴はなく、期待通りに扱えます。
これはGISで使われる型で、地表面をモデル化した空間上の幾何学図形を表現します。詳しいことはここで扱うには複雑すぎるので、また機会があれば別の記事で紹介したいと思います。
NULL値とNULL型の振舞いについて、細部の挙動に注意しながら紹介しました。
また、 BOOLEAN と GEOGRAPHY についても軽く触れました。