本文へスキップ
martechfarmDATA & TECHNOLOGY DOCS

Treasure Data / CDP 内を検索 · 全記事に戻す

Treasure Data / CDP

17 件

タイトルを選ぶと本文が開きます

Hiveはfalse、Trinoはtrueになる理由|整数除算の落とし穴

Treasure Data CJO完全解説②|ジャーニー設計と実務運用のポイント

Treasure Data CJO完全解説①|Customer Journey Orchestrationの基本構造

ファーストパーティデータとは何か|誤解されやすい意味とCDP活用の本質

Treasure Data導入で失敗する会社の共通点|CDPを使いこなせない5つの理由

中小企業がデータ活用で大企業に勝つ方法|小さな会社のCDP戦略

Treasure Dataが選ばれる理由|CDP導入で評価される強みと実務メリット

Digdagのparallel設定を最適化する方法|夜間バッチを高速化する実務設計

Treasure Data SQLでN日前・N日後の日付を計算する方法

Treasure Data SQLで日付差分を計算する方法|日数・時間数の出し方

Treasure Data SQLで先月・今月の月初月末を取得する方法

Treasure Data SQLで今日の日付・現在時刻を取得する方法

Treasure Data SQLで日付文字列をUNIXタイムに変換する方法

Treasure Data SQLでUNIXタイムを日付文字列に変換する方法

Treasure Data SQLで整数8桁の日付をUNIXタイムに変換する方法

Treasure Data CJOでジャーニーが更新されない原因と確認ポイント

Treasure Data CJOの処理完了を確認する方法|ジョブ状態と実行結果の見方

本文
記事一覧へ ↑

Hiveはfalse、Trinoはtrueになる理由|整数除算の落とし穴

「同じクエリなのに、結果が違う」

日付を整数で管理している現場では、こんなクエリをよく書く。

SELECT ( 20250515 / 100 ) <= 202505

20250515(yyyymmdd形式の日付)を 100 で割って月(yyyymm)に変換し、202505 と比較する。
一見シンプルな式だ。

ところがこのクエリ、実行するSQLエンジンによって結果が変わる。

エンジン結果
Hivefalse
Trinotrue

「バグか?」と焦るが、バグではない。
整数どうしの除算(/)に対する型の扱いが、エンジンごとに根本的に異なるからだ。


なぜ結果が変わるのか

答えはシンプルで、20250515 / 100 の計算結果の型が違う。

Hive の場合:浮動小数点除算

Hive は整数どうしの / を DOUBLE(浮動小数点数)として計算する。

20250515 / 100 = 202505.15 (DOUBLE)

その結果と 202505(INTEGER)を比較すると、

202505.15 <= 202505 → false

202505.15 は 202505 より大きいので、false になる。

Trino の場合:整数除算(切り捨て)

Trino は整数どうしの / を INTEGER として計算し、小数点以下を切り捨てる。

20250515 / 100 = 202505 (INTEGER、余り切り捨て)

その結果と 202505(INTEGER)を比較すると、

202505 <= 202505 → true

同じ値どうしの比較になるので、true になる。

まとめると

エンジン20250515 / 100 の結果型<= 202505 の評価
Hive202505.15DOUBLEfalse
Trino202505INTEGERtrue

仕様として正しいか

どちらが「間違い」ということはなく、SQL標準の解釈の違いだ。

ANSI SQL は整数どうしの除算について厳密な規定を設けておらず、実装に委ねている部分がある。Hive は BigQuery に近い「精度を失わない」方向の実装、Trino(旧 PrestoSQL)は多くのプログラミング言語(Python, Java, C など)と同じ「整数除算は整数で返す」方向の実装をとっている。

どちらが直感に近いかは人によるが、実務で引っかかりやすいのは確かだ。


実務でよく踏む場面

この挙動が問題になるのは、日付を整数で持っているテーブルで「日付 → 月」に変換するときだ。

SELECT *
FROM orders
WHERE ( order_date_int / 100 ) <= 202505

Hive ベースの Treasure Data でこれを実行すると、order_date_int / 100 は DOUBLE になる。
整数で持つ月(202505)との比較は微妙にずれるため、意図通りに絞り込めないことがある。


安全な書き方:CAST で型を明示する

エンジンに依存しない書き方にするには、CAST で明示的に整数に変換してから比較する。

-- 安全な書き方(Hive / Trino 共通)
SELECT ( CAST( 20250515 AS BIGINT ) / 100 ) <= 202505

CAST( 20250515 AS BIGINT ) / 100 は Hive でも Trino でも整数除算になり、結果は 202505(INTEGER)になる。

202505 <= 202505 → true (両エンジン共通)

あるいは、そもそも除算で月変換するのをやめて、文字列操作や専用の日付関数を使う方法もある。

-- 文字列 LEFT で月部分を切り出す(Hive / Trino 共通)
SELECT LEFT( CAST( 20250515 AS VARCHAR ), 6 )  -- '202505'

-- TD_TIME_FORMAT を使う(Treasure Data 環境)
SELECT TD_TIME_FORMAT( TD_DATE_TRUNC( 'month', time ), 'yyyyMM', 'JST' )

Treasure Data(Hive/Trino 混在環境)での注意点

同じクエリを Hive と Trino で使い回している場合、このような型の挙動の違いでサイレントに結果が変わるリスクがある。

特に次のようなケースで踏みやすい。

  • 日付を yyyymmdd の整数で持つテーブルを /100 で月変換しているとき
  • セグメント条件に INT列 / N の比較を使っているとき
  • Hive で書いたクエリを Trino に移行したとき

移行時は、数値リテラルどうしの除算が含まれる箇所を優先的に確認することを勧める。


まとめ

確認ポイントHiveTrino
整数 / 整数 の型DOUBLE(浮動小数点)INTEGER(切り捨て)
20250515 / 100 の値202505.15202505
<= 202505 の評価falsetrue
安全な対処法CAST で整数に変換CAST で整数に変換

同じ SQL が異なるエンジンでサイレントに違う結果を返すのは、デバッグが難しいバグの温床になる。
整数除算を使うときは CAST で型を明示し、エンジンに依存しないクエリを書く習慣をつけておこう。