BigQuery で日付(またはタイムスタンプ、DATETIME 型)から月初日を取得したい場合、たとえば “2017-05-24” から “2017-05-01” を得たいときは、Legacy SQL では UTC_USEC_TO_MONTH 関数を、Standard SQL では DATE_TRUNC() 関数を使えます。実は BigQuery には、日付から月初日・時間・週の初めなどを取得するための関数が一式そろっています。

Legacy SQL

月初日

タイムスタンプから月初日を取得する場合:

SELECT USEC_TO_TIMESTAMP(UTC_USEC_TO_MONTH(NOW()))

1501322861000000 は 2017-07-29 10:07:41 UTC なので、このクエリは 2017-07-01 00:00:00 UTC を出力します。

UTC_USEC_TO_MONTH 関数には Unix タイムスタンプ(マイクロ秒、int)を入力でき、その月の初日の Unix タイムスタンプを出力します。

UTC_USEC_TO_MONTH のような関数には、次のようなものもあります:

  • UTC_USEC_TO_WEEK
  • UTC_USEC_TO_HOUR
  • UTC_USEC_TO_DAY
  • UTC_USEC_TO_YEAR
月末日

月末日が必要な場合は、月初日を求めてから 1 秒戻します。たとえば次のようになります:

SELECT DATE_ADD( UTC_USEC_TO_MONTH( DATE_ADD( NOW(), 1, 'month' ) ), -1, 'second' )

現在のタイムスタンプを取得 -> 1 か月加算 -> 翌月の初日 -> 1 秒減算 -> 当月の月末日

週、時間、日、年でも同じ考え方です。

Standard SQL

Standard SQL は Legacy SQL よりも簡単です。TIMESTAMP 型には TIMESTAMP_TRUNC を、DATETIME 型と DATE 型には DATETIME_TRUNC と DATE_TRUNC を使えます。

月初日

SELECT TIMESTAMP_TRUNC(CURRENT_TIMESTAMP(), MONTH)

第 2 引数で、月初日にするか、週の初日にするかなどを指定します。注意点として、第 2 引数は文字列ではありません!

第 2 引数には次の値を使えます:

  • DAY
  • WEEK
  • MONTH
  • QUARTER
  • YEAR
DATE 型を入力したい場合は DATE_TRUNC を使う必要があります。DATETIME 型も同様です。

月末日

Legacy SQL と同じように、一部の関数を Standard SQL 用のものに変えるだけです。たとえば次のようになります:

SELECT DATE_SUB(DATE_TRUNC(DATE_ADD(CURRENT_DATE(), INTERVAL 1 MONTH), MONTH), INTERVAL 1 DAY)

TIMESTAMP_ADD は MONTH をサポートしていないため、先に TIMESTAMP を DATETIME か DATE に変換する必要があります。