SnowflakeでSQLを書いていて、「同じ日付なのに、なぜかa_date <= b_dateが期待と違う結果になる…」といった経験はありませんか?

それは、タイムゾーンの罠にハマっている可能性があります。

この記事では、Snowflakeにおけるタイムゾーン付きデータ(TIMESTAMP_TZ)とタイムゾーンなしデータ(TIMESTAMP_NTZ)の比較で発生する問題と、それをJST(日本標準時)ベースで簡易に解決するSQLを紹介します。

スポンサーリンク

なぜ比較結果が狂うのか?

ご指摘のケースでは、以下のようなデータで比較が行われていました。

項目データ型(想定)
a_dateTIMESTAMP_NTZ'2025-12-09 00:00:00'
b_dateTIMESTAMP_TZ'2025-12-09 00:00:00 +09:00'

a_date(タイムゾーンなし)とb_date(タイムゾーンあり)の「見た目の日付」は同じです。しかし、この状態で比較を実行すると、a_date <= b_dateFALSE(つまり、a_dateの方が新しい)と判定されてしまう場合があります。

タイムゾーンによる自動変換

Snowflakeでは、異なるタイムスタンプ型が混在した比較が行われる際、b_date(タイムゾーン付き)の情報が優先され、内部的にUTCに変換されてから比較されることが原因です。

  1. a_date (NTZ): 2025-12-09 00:00:00 (NTZ)
  2. b_date (TZ): 2025-12-09 00:00:00 +09:00 $\to$ 2025-12-08 15:00:00 UTCに変換
  3. a_dateの擬似UTC変換: a_dateをセッションタイムゾーン(例: UTC)と見なすと、2025-12-09 00:00:00 UTCのまま
  4. 比較: 2025-12-09 00:00:00 $\le$ 2025-12-08 15:00:00 $\to$ FALSEa_dateの方が新しいと判定!)

このように、データ型が揃っていないために、私たちが期待する「日本の時刻としての比較」が行われなくなってしまうのです。

JST(見た目の時刻)で簡易比較する解決策

最もシンプルで、日本のユーザーが入力・確認した時刻(JST)として比較したい場合に有効な方法は、b_dateからタイムゾーン情報だけを削除し、タイムゾーンなしの時刻 (TIMESTAMP_NTZ) に揃えることです。

これは、CAST::を使ってデータ型を変換するだけで実現できます。

💡 解決コード

a_date <= b_date::TIMESTAMP_NTZ

または CAST を使用して

a_date <= CAST(b_date AS TIMESTAMP_NTZ)

動作の仕組み

  1. b_dateをJSTの見た目で固定:'2025-12-09 00:00:00 +09:00' $\to$ 2025-12-09 00:00:00 (TIMESTAMP_NTZ)
  2. JST時刻同士の比較:2025-12-09 00:00:00 $\le$ 2025-12-09 00:00:00

この方法により、タイムゾーンの自動変換が起こらず、「日本の日付・時刻」として単純に大小が比較されます。この例では、期待通りTRUEと判定されます。

スポンサーリンク

まとめ

Snowflakeでタイムスタンプを比較する際は、必ず両方のデータ型を揃えましょう。特に、タイムゾーン付き (TIMESTAMP_TZ) とタイムゾーンなし (TIMESTAMP_NTZ) が混在する場合は注意が必要です。

  • JST(見た目の時刻)で比較したい場合:SQLa_date <= b_date::TIMESTAMP_NTZ

より厳密にUTCで管理・比較したい場合は、両方をTIMESTAMP_TZに変換し、UTCで統一する手法が推奨されますが、簡易的に対応するなら上記の変換が最も手軽です。

タイムスタンプの型変換をマスターして、Snowflakeのデータ処理を快適にしましょう!


この記事が気に入ったら『目黒で働く分析担当の作業メモ』ご支援をお願いします!

※OFUSEに飛びます


おすすめの記事