みなさんこんにちは!ヒロポンです!
「今日の日付ってどう書くんだっけ」
「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

日付だけ取る(時刻を切り落とす)
-- 時刻を捨てて日付だけ(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(単位, 増減, 基準日)。マイナスを渡せば「前」です。DAY を MONTH や YEAR に変えれば月・年単位。
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 のスタイル番号や暗黙の型変換まわりでハマったことがある人は、型変換そのものを整理した 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月や月末当日まで含めて確認したのがこれ。全部一致してます。

③ 文字列との比較で暗黙の型変換が起きる
WHERE 日付列 = '2026-06-23' のように文字列リテラルと比較する時、SQL Server が裏で暗黙に型変換をかけます。
多くは問題ない。けど地域設定(カルチャ)によって '06/07/2026' が6月7日なのか7月6日なのか、解釈が割れる。
日付リテラルは '2026-06-23'(ISO 形式 YYYY-MM-DD)か '20260623' で書くのが事故りにくいです。スラッシュ区切りは環境依存になるので避けるのが無難。
現場メモ: 古い環境で動かす前提
この記事のコードは、断りがなければ SQL Server 2016 で動く前提で書いてます。
EOMONTH・DATEFROMPARTS・FORMAT はどれも 2012 以降。なので 2016 ならフルで使えます。
逆に言うと、それより古い環境に当たった時は EOMONTH と FORMAT だけ要注意。代替の書き方は上に置いたので、バージョンを確認してから貼ってください。
客先の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()。返る型が datetime か datetime2 かの違いなので、列の型と揃えておくと暗黙変換を減らせます。
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 で経歴詳細を見る
次に読むべき記事
- SQL Server の CAST と CONVERT で業務SEがハマる3箇所 — 日付フォーマットの CONVERT スタイル番号や暗黙変換をもっと深く知りたい人向け
- SQL Server UPDATE … FROM SELECT 3パターン — 取った日付で UPDATE する時の書き方が気になる人向け
- C# DateTime と DateTimeOffset の違い・タイムゾーン処理の正解 — SQL で取った日付を C# 側で扱う時のタイムゾーン落とし穴
- C# TryParse の正解(int / DateTime / Enum) — 画面入力の日付文字列を安全にパースしたい時の応用編
- 客先常駐しかない、と思ってる業務SEへ — SQL を読み書きできる業務SEの市場価値を、キャリア軸で考えたい人へ
以上!
同じように日付処理で毎回ググってる人がいたら、どんどんシェア待ってるぜ!!


コメント