1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RedshiftからBigQueryへのクエリ変換でハマったポイント

Posted at

はじめに

分析環境がRedshiftからBigQueryへ移行することに伴い、従来のクエリの書き換えをすることになりました。簡単に終わるだろう思っていたら、いくつかハマったポイントがあったので共有します。

ハマったこと

データ型が異なる比較はBigQueryが厳格

Redshiftでは、異なるデータ型を比較することがかなり許容されていたが、BQでは厳格。例えば、TIMESTAMP、DATETIME、DATEの比較はできない。
そもそも異なるデータ型で比較するのが気持ち悪いので、BQのほうが処理的には良いと思う。(Redshiftは良くも悪くも、異なるデータ型をよしなに比較してくれている)

-- Redshift 文字列とdateを比較してもエラーは出ない
select substring(cast(date('2021-12-01') as VARCHAR), 1, 10) >= dateadd(day, -365, date('2021-12-01'))
-- アウトプット true

-- BigQuery 異なるデータ型は比較することができない
select substring(cast(date('2021-12-01') as string), 1, 10) >= date_add(date('2021-12-01 00:00:00'), interval - 365 day)
/* エラーメッセージ
No matching signature for operator >= for argument types: STRING, DATE. Supported signature: ANY >= ANY at [4:1]
*/

DATE_TRUNC関数で週の最初の曜日が異なる

デフォルトだと、WEEKの開始日が以下のように異なる。
Redshift: 月曜日
BigQuery: 日曜日
もしBigQueryで月曜開始にしたい場合は、DATE_TRUNC(date, WEEK(MONDAY)) とすれば挙動が揃う。

また戻り値も異なるので注意。
Redshift: TIMESTAMP(公式ドキュメント
BigQuery: DATE (公式ドキュメント

-- Redshift 
select DATE_TRUNC('week', date('2021-12-01'))
-- アウトプット 2021-11-29 00:00:00.000000

-- BigQuery
select DATE_TRUNC('2021-12-01', week)
-- アウトプット 2021-11-28

-- 参考:第2引数を変えると任意の曜日を開始日にできる
select DATE_TRUNC('2021-12-01', week(monday))
-- アウトプット 2021-11-29

特定の日時でのユーザーの年齢を算出するクエリ

RedshiftでMONTHS_BETWEEN関数を使用していたが、BigQueryにはMONTHS_BETWEENに相当する関数が無いので、以下のように修正。

-- Redash
select TRUNC(MONTHS_BETWEEN(date('2022-12-01'), date('2021-12-01')) / 12) as age

-- BigQuery 年齢を出すクエリは色々あるが、汎用的なものを採用
select TRUNC((CAST(FORMAT_DATE('%Y%m%d', date('2022-12-01')) AS INT64) - CAST(FORMAT_DATE('%Y%m%d',date('2021-12-01')) AS INT64)) / 10000) as age

緯度経度を使用した2地点間の距離計算の結果が微妙にずれる (BigQueryが世界測地系 WGS84での距離計算には未対応)

Redshiftでは2地点間の距離をより地球上の距離に近く(世界測地系 WGS84を使用して)計算できるが、Bigqueryでは現在、完全な球体の距離でしか計測できないらしい。

公式ドキュメントからの抜粋

任意指定の use_spheroid パラメータは、この関数で距離が測定される方法を決定します。use_spheroid が FALSE の場合、完全な球体の表面上の距離が測定されます。
use_spheroid パラメータで現在サポートされている値は FALSE だけです。use_spheroid のデフォルト値は FALSE です。

-- 東京駅と神田駅の距離を計算してみる。

-- Redshift デフォルトでWGS84を使った距離を計算できる
select ST_DistanceSphere(st_point(139.7671, 35.6812), st_point(139.7709, 35.6918)) / 1000 as distance_in_km
-- アウトプット 1.2276163950893566

-- BQ WGS84には対応しておらず、完全な球体の距離でしか計算できない
select ST_Distance(st_geogpoint(139.7671, 35.6812), st_geogpoint(139.7709, 35.6918)) / 1000 distance_in_km
-- アウトプット 1.227616631823407
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?