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
月末日
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 に変換する必要があります。