SQL Server で日付を扱う T-SQL コピペ集 — 今日・N日前・月初月末・フォーマット

みなさんこんにちは!ヒロポンです!

「今日の日付ってどう書くんだっけ」

「N日前は…DATEADD のマイナスでいいんやっけ?」

「てか月末ってどう取るの??」

SQL Server で日付を触るたび、これを毎回ググってる人。

俺です。というか業務SEはだいたいそうじゃないですか??

日付処理って使う頻度は高いのに、書き方が頭に残らない。GETDATE くらいはスッと出る。でも月初・月末・経過日数あたりで毎回手が止まる。

なので現場でそのままコピペできる形で全部並べました。今日からググるの、やめましょう。

目次

結論: よく使う日付処理はこの6つで足りる

先に結論だけ。

SQL Server の日付処理は、だいたいこれで回ります。

  • 今日・現在時刻GETDATE() / SYSDATETIME()
  • 日付だけ(時刻を切る)CAST(... AS date)
  • N日前・N日後DATEADD()
  • 2つの日付の差DATEDIFF()
  • 月初・月末DATEFROMPARTS() / EOMONTH()
  • 表示(yyyy/MM/dd など) → 大量行は CONVERT()、柔軟さ重視は FORMAT()

以上!

以下、全部コピペで動く形で置いていきます。SQL Server 2016 でも動く書き方を基本にしてます。

まず押さえる: 日付の「型」と現在日時の取り方

コードに行く前に1つだけ。日付の「型」の話です。

GETDATE() が返すのは datetime 型(8バイト・約3.3ミリ秒精度)。秒より細かい精度が要るなら SYSDATETIME()datetime2 型)を使います。

ここで地味に効いてくるのが型選び。

Pro SQL Server Internals(Dmitri Korotkevitch, p.58・英語原書を日本語訳)には、こんな指摘があります。

必要な精度に応じて適切な日付/時刻型を選ぶこと。たとえば受注システムで、注文がいつ入ったかを1分または1秒の精度で記録できれば十分なら、datetime(8バイト)ではなく smalldatetime(4バイト)や datetime2(0)(6バイト)を使うとよい。

業務SE視点で言い直すと、GETDATE() をそのまま入れると datetime(8バイト)で固定です。

秒精度で足りるログ系の列を、何も考えず datetime で持ってる現場、けっこう多いんですよね。

行数が数千万になるテーブルだと、この型選びがストレージとI/Oにじわっと効いてくる。新規テーブルを切る時だけでも思い出してください。

で、本題のコピペ集にいきます。

コピペで動く: 日付処理の T-SQL

各スニペット、「何を出すか」を見出しにしてます。必要なところだけ拾ってください。

今日・現在時刻を取る

-- 現在の日時(datetime / 約3.3ミリ秒精度)
SELECT GETDATE();              -- 2026-06-23 13:05:42.120

-- もっと細かい精度がほしい(datetime2)
SELECT SYSDATETIME();          -- 2026-06-23 13:05:42.1234567

GETDATE と SYSDATETIME の実行結果。datetime と datetime2 で小数秒の精度が違う様子

日付だけ取る(時刻を切り落とす)

-- 時刻を捨てて日付だけ(00:00:00 になる)
SELECT CAST(GETDATE() AS date);   -- 2026-06-23

date 型にキャストするのが、今は一番素直です。

昔よく見た CONVERT(varchar, GETDATE(), 112) で文字列にして…みたいな小細工。あれもう要りません。

N日前・N日後・Nヶ月後

-- 7日前
SELECT DATEADD(DAY, -7, GETDATE());
-- 30日後
SELECT DATEADD(DAY, 30, GETDATE());
-- 1ヶ月後(月末は自動で丸めてくれる)
SELECT DATEADD(MONTH, 1, GETDATE());

DATEADD(単位, 増減, 基準日)。マイナスを渡せば「前」です。DAYMONTHYEAR に変えれば月・年単位。

2つの日付の差・経過日数

-- 入社日から今日までの経過日数
SELECT DATEDIFF(DAY, '2020-04-01', GETDATE());   -- 例: 2273

注意は引き算の向き。DATEDIFF(単位, 開始, 終了) で「開始→終了」の差です。逆にすると符号が反転する。ここだけ間違えないように。

月初・月末を取る

-- 当月の月初(1日)
SELECT DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1);

-- 当月の月末
SELECT EOMONTH(GETDATE());

-- 先月末・来月末も EOMONTH の第2引数でいける
SELECT EOMONTH(GETDATE(), -1);   -- 先月末
SELECT EOMONTH(GETDATE(),  1);   -- 来月末

月末は EOMONTH 一発。これがいい感じに楽。

ただし EOMONTH は SQL Server 2012 以降なので、そこだけ後で触れます。

yyyy/MM/dd などで表示する

-- CONVERT のスタイル番号で yyyy/mm/dd
SELECT CONVERT(varchar(10), GETDATE(), 111);   -- 2026/06/23
-- yyyy-mm-dd(ISO 風)
SELECT CONVERT(varchar(10), GETDATE(), 23);    -- 2026-06-23

-- FORMAT なら書式を直に指定できる
SELECT FORMAT(GETDATE(), 'yyyy/MM/dd');        -- 2026/06/23
SELECT FORMAT(GETDATE(), 'yyyy年M月d日');       -- 2026年6月23日

CONVERT のスタイル番号 111 と 23 の実行結果。yyyy/mm/dd と yyyy-mm-dd が返る様子

表示変換はこんな感じで手段が複数あって、ここが一番の迷いどころ。

下に整理しておきます。

日付の表示変換3手法(CONVERT スタイル番号 / FORMAT / CAST)を、大量行での速さ・書式の自由度・カルチャ非依存・対応バージョンで比較した表

CONVERT のスタイル番号や暗黙の型変換まわりでハマったことがある人は、型変換そのものを整理した SQL Server の CAST と CONVERT で業務SEがハマる3箇所 も合わせてどうぞ。

別タブで開いて、後で読んでくださいな。日付フォーマットの土台になります。

ハマりポイント: 知らないと地味に効くやつ

コピペで動かす前に、現場で踏みやすいのを3つだけ。

① FORMAT は大量行で遅い

FORMAT は書式を文字列で自由に書けて便利なんですよね。ただ中身は1行ずつ .NET の書式処理を呼び出す作り。なので数万〜数十万行を一気に変換すると、目に見えて遅くなります。

俺もバッチで全行 FORMAT してたのを CONVERT(..., 111) に置き換えただけで、処理時間がガクッと落ちたことがありました。あの時は地味に救われた。

画面に出す少量は FORMAT、バッチや大量行は CONVERT。これが現場の基本線です。

② EOMONTH は SQL Server 2012 以降

月末が一発で取れる EOMONTH、めっちゃ便利なんですが 2012 からの関数です。2016 の現場なら問題なし。

もし 2008 R2 みたいな化石が現役なら、月末はこう書きます。

-- EOMONTH が使えない古い環境での月末
SELECT DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0));

「翌月の月初の前日 = 今月末」という計算です。読みにくいけど、ちゃんと動きます。

この代替式が EOMONTH とちゃんと同じ月末を返すか、うるう年の2月や月末当日まで含めて確認したのがこれ。全部一致してます。

EOMONTH と代替式の月末日が、うるう年2月や年境界を含む複数の基準日で完全一致した検証結果

③ 文字列との比較で暗黙の型変換が起きる

WHERE 日付列 = '2026-06-23' のように文字列リテラルと比較する時、SQL Server が裏で暗黙に型変換をかけます。

多くは問題ない。けど地域設定(カルチャ)によって '06/07/2026' が6月7日なのか7月6日なのか、解釈が割れる。

日付リテラルは '2026-06-23'(ISO 形式 YYYY-MM-DD)か '20260623' で書くのが事故りにくいです。スラッシュ区切りは環境依存になるので避けるのが無難。

現場メモ: 古い環境で動かす前提

この記事のコードは、断りがなければ SQL Server 2016 で動く前提で書いてます。

EOMONTHDATEFROMPARTSFORMAT はどれも 2012 以降。なので 2016 ならフルで使えます。

逆に言うと、それより古い環境に当たった時は EOMONTHFORMAT だけ要注意。代替の書き方は上に置いたので、バージョンを確認してから貼ってください。

客先のSQL Serverのバージョン、意外と SELECT @@VERSION; 一発で確認できます。

動作確認メモ: 本文の T-SQL は SQL Server 2019 互換エンジンで実行確認済みです(GETDATE / CAST / DATEADD / DATEDIFF / DATEFROMPARTS / EOMONTH と、EOMONTH 代替式の月末一致はうるう年2月や年境界を含む複数日付で検証済み)。FORMAT だけは検証環境の都合で実行できていませんが、SQL Server 2012 以降なら FORMAT(GETDATE(), 'yyyy/MM/dd')2026/06/23 のように正しく動きます。古い環境に貼る時はバージョンだけ確認してください。

まとめ・チートシート

毎回ググってたやつ、これで手元に揃いました!!

やりたいこと 関数 コピペ
今日の日時 GETDATE() SELECT GETDATE();
日付だけ CAST CAST(GETDATE() AS date)
N日前 DATEADD DATEADD(DAY, -7, GETDATE())
経過日数 DATEDIFF DATEDIFF(DAY, 開始, 終了)
月初 DATEFROMPARTS DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()),1)
月末 EOMONTH EOMONTH(GETDATE())
yyyy/MM/dd 表示 CONVERT CONVERT(varchar(10), GETDATE(), 111)

ブックマークして、次に手が止まったらここに戻ってきてください。それでいい感じに回るはずです。

よくある質問

Q1. GETDATE() と SYSDATETIME()、どっちを使えばいい?

ふつうの業務処理なら GETDATE() で足ります。ミリ秒より細かい精度(ログの順序保証など)が要る時だけ SYSDATETIME()。返る型が datetimedatetime2 かの違いなので、列の型と揃えておくと暗黙変換を減らせます。

Q2. なぜ FORMAT じゃなくて CONVERT を勧めるんですか? FORMAT のほうが書きやすいのに

書きやすさは FORMAT の勝ちです。ただ大量行で遅い。そこだけの差です。なので「画面表示やレポートの少量データは FORMAT、バッチで何万行も変換するなら CONVERT」と使い分けるのが現実的。最初から全部 CONVERT にする必要はないっす。

Q3. 文字列で日付を渡すと、たまに結果がおかしくなります

カルチャ依存の暗黙変換が原因のことが多いです。'2026/06/23' みたいなスラッシュ区切りは環境で解釈が変わるので、'2026-06-23''20260623' で渡してください。これだけで誤変換はほぼ消えます。

Q4. 月初から今日までのデータを抽出したいんですが、WHERE はどう書く?

WHERE 日付列 >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) AND 日付列 < DATEADD(DAY, 1, CAST(GETDATE() AS date)) のように書けます。列 >= 月初 AND 列 < 明日 の形にすると、時刻付きの列でも取りこぼしません。ちなみに上限を CAST(GETDATE() AS date) + 1 と書きたくなるけど、date 型に + 1 は型エラー(Msg 206)になるので、DATEADD(DAY, 1, ...) を使ってください。CONVERT で日付を文字列化して比較するより、こっちのほうが速いしインデックスも効きます。

この記事の参考文献

日付/時刻型の選び方は、以下の書籍の知見を業務SE視点でかみ砕いたものです。

  • Pro SQL Server Internals(Dmitri Korotkevitch 著 / Apress・2016)— SQL Server の内部構造(ストレージ / インデックス / トランザクション / 実行計画)を DBA レベルで深掘りした技術書。データストレージの章(p.58)は、日付/時刻型を精度とストレージで選ぶ判断の土台になります。

執筆者

バイブス父さん — 業務 SE 7 年 (SIer 正社員 2 / フリーランス 5)。 現職は SEO 直轄部の AI アドバイザー兼 PL、 副業で中小 SIer の CTO。 SIer の正社員からフリーランスに転じ、 複数のエージェント経由で案件を回してきた経験ベースで「業務 SE 視点」 の技術 + キャリア記事を書いています。

🐦 X: @hiro_progra0524 (日々の現場メモ更新中)
📝 About Me で経歴詳細を見る

次に読むべき記事

以上!

同じように日付処理で毎回ググってる人がいたら、どんどんシェア待ってるぜ!!


この記事が気に入ったら
いいねしてね!

どんどんシェア待ってるぜ!!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次