対応エンジン
| エンジン | 対応 | 備考 |
|---|---|---|
| TD(Presto) | ✅ | UNIXタイムの差分で計算 |
| Trino / Presto | ✅ | date_diff関数が使える |
| Hive | ✅ | datediff関数が使える |
こんなときに使う
「初回購買から2回目購買までの日数」「会員登録からの経過日数」「最終ログインから何日空いているか」など、2つの日付の間隔を計算したい場面で使います。
TDでの実装
結論:このSQLを使う
TDではUNIXタイム(秒)同士の差を取って単位で割ります。
SELECT
-- 日数差
(unix_time_b - unix_time_a) / 86400 AS diff_days,
-- 時間差
(unix_time_b - unix_time_a) / 3600 AS diff_hours,
-- 分差
(unix_time_b - unix_time_a) / 60 AS diff_minutes
FROM your_table
入力例:
unix_time_a:1704034800(2024-01-01 00:00:00 JST)unix_time_b:1706713200(2024-02-01 00:00:00 JST)
出力例:
diff_days:31.0diff_hours:744.0
小数点を切り捨てたい場合
SELECT
FLOOR((unix_time_b - unix_time_a) / 86400) AS diff_days
FROM your_table
-- → 31
今日からの経過日数を動的に計算
SELECT
user_id,
register_time,
FLOOR((TD_SCHEDULED_TIME() - register_time) / 86400) AS days_since_register
FROM user_table
Trino / Prestoでの実装
date_diff関数で単位を指定して差分を計算できます。
SELECT
-- 日数差
date_diff('day', timestamp_a, timestamp_b) AS diff_days,
-- 時間差
date_diff('hour', timestamp_a, timestamp_b) AS diff_hours,
-- 分差
date_diff('minute', timestamp_a, timestamp_b) AS diff_minutes,
-- 月差
date_diff('month', timestamp_a, timestamp_b) AS diff_months
FROM your_table
UNIXタイムから変換する場合はfrom_unixtimeを組み合わせます。
SELECT
date_diff(
'day',
from_unixtime(unix_time_a) AT TIME ZONE 'Asia/Tokyo',
from_unixtime(unix_time_b) AT TIME ZONE 'Asia/Tokyo'
) AS diff_days
FROM your_table
Hiveでの実装
datediff関数で日数差を計算できます。
SELECT
-- 日数差(date型またはyyyy-MM-dd形式の文字列を渡す)
datediff(date_b, date_a) AS diff_days,
-- 時間差(UNIXタイムから計算)
(unix_time_b - unix_time_a) / 3600 AS diff_hours
FROM your_table
Hiveのdatediffは日数のみ対応しています。時間・分の差分はTDと同様に秒数差から計算します。
エンジン別まとめ
| エンジン | 日数差 | 時間差 | 月差 |
|---|---|---|---|
| TD | (unix_b - unix_a) / 86400 | (unix_b - unix_a) / 3600 | 直接計算不可 |
| Trino / Presto | date_diff('day', a, b) | date_diff('hour', a, b) | date_diff('month', a, b) |
| Hive | datediff(b, a) | (unix_b - unix_a) / 3600 | 直接計算不可 |
⚠️ よくあるミス
日付文字列のまま引き算しようとする(TD)
-- ❌ 文字列同士は引き算できない
'2024-02-01' - '2024-01-01'
-- ✅ TD_TIME_PARSEでUNIXタイムに変換してから計算
(
TD_TIME_PARSE('2024-02-01', 'Asia/Tokyo')
- TD_TIME_PARSE('2024-01-01', 'Asia/Tokyo')
) / 86400
-- → 31
date_diffの引数の順序を間違える(Trino / Presto)
-- ❌ 順序が逆だと負の値になる
date_diff('day', timestamp_b, timestamp_a)
-- → -31
-- ✅ 古い日付を第2引数・新しい日付を第3引数に
date_diff('day', timestamp_a, timestamp_b)
-- → 31
結果が小数になることを考慮しない(TD)
-- ❌ 時刻がずれていると日数が小数になる
-- unix_time_a = 2024-01-01 00:00:00
-- unix_time_b = 2024-02-01 12:00:00
(unix_time_b - unix_time_a) / 86400
-- → 31.5
-- ✅ FLOOR・CEILで整数に丸める
FLOOR((unix_time_b - unix_time_a) / 86400)
-- → 31
秒数早見表(TD用)
| 単位 | 秒数 |
|---|---|
| 1分 | 60 |
| 1時間 | 3600 |
| 1日 | 86400 |
| 7日(1週間) | 604800 |
| 30日 | 2592000 |
| 365日(1年) | 31536000 |
よくある応用:初回購買から2回目購買までの日数(TD)
SELECT
user_id,
first_purchase_time,
second_purchase_time,
FLOOR(
(second_purchase_time - first_purchase_time) / 86400
) AS days_to_repurchase
FROM purchase_table
まとめ
| ポイント | 内容 |
|---|---|
| TDは秒数差で計算 | (unix_b - unix_a) / 86400で日数差 |
| 整数で欲しい | FLOORで切り捨て・CEILで切り上げ |
| Trinoはdate_diffが便利 | 単位を引数で指定できる・月差も取れる |
| Hiveはdatediffが日数のみ | 時間差は秒数から計算 |