役に立たない BigQuery の話

ある BigQuery の CSV インポートのときのことである。

CSV のスキーマ定義は事前に得られていたので、テーブル定義を先に作成した。CSV を LOAD DATA INTO と行いたかったのだが、

Cannot add fields (field: date_field_0)

Cannot add fields

のような警告がでて、入らない…。

ところが、BigQuery の「テーブルを作成」から、スキーマを自動認識にしたところ、「列名は自動生成だが、データ型は同じ」テーブルができたのである。「いやいや、それが作成したかったテーブル…」なのだが…。

一方、さらに、

`LOAD DATA INTO logs.8bbfede3-7df2-4421-b1db-f3fa96c0dc8b
(
request_date DATE,
request_time TIME,
protocol STRING,
client_ip STRING,
...```

のようにスキーマを指定すると…

Error while reading data, error message: Unable to parse; line_number: 1 byte_offset_to_start_of_line: 0 column_index: 0 column_name: "request_date" column_type: DATE value: "2023/08/17" File: gs://h ...

この辺りで何が起こっているか分かりますか?

答え

自動の罠である。

CSV データをテーブルに読み込む によれば、

Date。DATE 型の列は YYYY-MM-DD の形式にする必要があります。

Datetime。DATETIME 型の列は YYYY-MM-DD HH:MM:SS[.SSSSSS] の形式にする必要があります。
Timestamp。BigQuery はさまざまなタイムスタンプ形式に対応しています。タイムスタンプには日付の部分と時刻の部分を含める必要があります。
日付の部分は YYYY-MM-DD 型または YYYY/MM/DD 型にできます。

はい、Date は 2023/08/17 だと受け取ってくれないのである。

ところが、これはおせっかい機能なのだろう、「何も指定せずに」読み込んだ場合は date_field_0 として、DATE 型で読み込んでくれるのだ。スキーマを指定すると、ダメ…。

date_field_0

一度 TIMESTAMP として読み込み、DATE に変換する…といった内部プロセスがあるに違いない。

SELECT DATE('2023/08/17');

を実行しようとすると、

Could not cast literal "2023/08/17" to type TIMESTAMP at [2:13]

のようなエラーが出て読み込めない。

SELECT PARSE_DATE('%Y/%m/%d', '2023/08/17');

これは動作する。

ということで、

  • "2023/08/17" は全自動だと DATE になる
  • "2023/08/17" を DATE 列に明示的に読み込むことはできない
  • SELECT DATE('2023/08/17'); はエラー

となった。回避策は簡単で、一度 STRING 型として読み込み、そのデータを利用して、PARSE_DATE を行えば良い。