対応エンジン
| エンジン | 対応 | 備考 |
|---|---|---|
| TD(Presto) | ✅ | UNIXタイムに秒数を加減算 |
| Trino / Presto | ✅ | intervalを使う |
| Hive | ✅ | date_add・date_subを使う |
こんなときに使う
「30日前以降に購買したユーザーを抽出」
「登録日の7日後にフォローメールを送りたい」
「直近1週間のデータを毎日自動で集計したい」など、基準日からN日ずらした日時を動的に計算したい場面で使います。
TDでの実装
UNIXタイムに秒数を足し引きします。
SELECT
-- 30日前
TD_SCHEDULED_TIME() - 86400 * 30 AS days_30_ago,
-- 7日後
TD_SCHEDULED_TIME() + 86400 * 7 AS days_7_later
FROM your_table
86400は1日の秒数(60秒 × 60分 × 24時間)です。日数を掛けて足し引きするだけでN日前・N日後が計算できます。
基準日を固定してN日後を計算
今日ではなく、テーブル内の日付カラムを基準にする場合も同じ考え方です。
SELECT
user_id,
register_time,
register_time + 86400 * 7 AS follow_mail_time, -- 登録7日後
register_time + 86400 * 30 AS month_mail_time -- 登録30日後
FROM user_table
日付文字列を基準にする場合
SELECT
TD_TIME_PARSE('2024-01-01', 'Asia/Tokyo') + 86400 * 7 AS days_7_later
-- → 1704639600(2024-01-08 00:00:00 JST)Trino / Prestoでの実装
intervalキーワードで直感的に書けます。
SELECT
-- 30日前
now() - interval '30' day AS days_30_ago,
-- 7日後
now() + interval '7' day AS days_7_later,
-- 1ヶ月前(月単位で計算)
now() - interval '1' month AS month_1_ago,
-- 1年後
now() + interval '1' year AS year_1_later
UNIXタイムで結果が欲しい場合はto_unixtimeを組み合わせます。
SELECT
to_unixtime(
now() AT TIME ZONE 'Asia/Tokyo' - interval '30' day
) AS days_30_ago_unixHiveでの実装
date_add・date_subで日数を加減算します。
SELECT
-- 30日前
date_sub(current_date, 30) AS days_30_ago,
-- 7日後
date_add(current_date, 7) AS days_7_later,
-- 1ヶ月前
add_months(current_date, -1) AS month_1_ago,
-- 1ヶ月後
add_months(current_date, 1) AS month_1_laterエンジン別まとめ
| エンジン | N日前 | N日後 | N月前後 |
|---|---|---|---|
| TD | 基準unix - 86400 * N | 基準unix + 86400 * N | 31日ずらして月調整 |
| Trino / Presto | now() - interval 'N' day | now() + interval 'N' day | interval 'N' month |
| Hive | date_sub(date, N) | date_add(date, N) | add_months(date, ±N) |
⚠️ よくあるミス
月単位でずらすときに日数計算を使う(TD)
-- ❌ 30日引いても「1ヶ月前の同じ日」にはならない
-- 例:3月31日の30日前 → 2月29日(うるう年以外は存在しない)
TD_SCHEDULED_TIME() - 86400 * 30
-- ✅ 月をずらしたい場合は31日引いて月をまたいでから月初を取得
-- → 詳しくは[日付]先月・今月の1日と末日を取得する方法を参照時刻がずれることを考慮しない(TD)
-- ❌ 86400秒引くだけでは時刻がそのまま残る
TD_SCHEDULED_TIME() - 86400 * 30
-- → 30日前の同じ時刻(例:2024-01-01 15:00:00)
-- ✅ 日付の開始時刻(00:00:00)に揃えたい場合はTD_DATE_TRUNCと組み合わせる
TD_DATE_TRUNC('day', TD_SCHEDULED_TIME() - 86400 * 30, 'Asia/Tokyo')
-- → 30日前の00:00:00よくある応用
直近30日のデータを絞り込む(TD)
SELECT *
FROM your_table
WHERE TD_TIME_RANGE(
time,
TD_SCHEDULED_TIME() - 86400 * 30,
TD_SCHEDULED_TIME()
)
登録から7日以内のユーザーを抽出(TD)
SELECT *
FROM user_table
WHERE TD_SCHEDULED_TIME() - register_time <= 86400 * 7直近7日・30日・90日を同時に集計(TD)
SELECT
COUNT(CASE WHEN TD_SCHEDULED_TIME() - time <= 86400 * 7 THEN 1 END) AS cnt_7days,
COUNT(CASE WHEN TD_SCHEDULED_TIME() - time <= 86400 * 30 THEN 1 END) AS cnt_30days,
COUNT(CASE WHEN TD_SCHEDULED_TIME() - time <= 86400 * 90 THEN 1 END) AS cnt_90days
FROM your_table秒数早見表
| 期間 | 秒数 |
|---|---|
| 1時間 | 3600 |
| 1日 | 86400 |
| 7日(1週間) | 604800 |
| 30日 | 2592000 |
| 90日 | 7776000 |
| 365日(1年) | 31536000 |
まとめ
| ポイント | 内容 |
|---|---|
| TDはUNIXタイムに秒数を加減算 | 86400 * NでN日分 |
| Trinoはintervalが使えてシンプル | 月・年単位も直感的に書ける |
| 月単位のずらしはTDは注意 | 日数計算では月末の扱いがズレる |
| 時刻を揃えたい場合 | TD_DATE_TRUNCと組み合わせる |