1. はじめに
MySQLで日付を扱う機能は、データベース操作の中でも非常に重要です。たとえば、売上データを日付ごとに集計したり、過去一定期間の記録を検索したりするシナリオでは、日付の比較が必須となります。
本記事では、MySQLの日付操作や比較の基礎から応用例、さらにはパフォーマンスを最適化する方法までを詳しく解説します。初心者から中級者まで、あらゆるレベルのユーザーが役立てられる内容を目指しています。
2. MySQLの日付データ型の概要
日付データ型の種類と特徴
MySQLでは、以下の3つの主要な日付データ型があります。それぞれの特徴を簡単に解説します。
- DATE
- 格納内容: 年月日(
YYYY-MM-DD
) - 特徴: 時間情報を含まないため、単純な日付の管理に適しています。
- 使用例: 誕生日、締め切り日。
- DATETIME
- 格納内容: 年月日と時刻(
YYYY-MM-DD HH:MM:SS
) - 特徴: 時刻情報を含むため、正確な日時を記録するのに適しています。
- 使用例: 作成日時、最終更新日時。
- TIMESTAMP
- 格納内容: 年月日と時刻(
YYYY-MM-DD HH:MM:SS
) - 特徴: タイムゾーンに依存するため、異なる地域間の日時管理に便利です。
- 使用例: ログデータ、トランザクション記録。
使用するべきデータ型の選択基準
- 時刻が不要なら、DATEを選択。
- 時刻を含めたい場合は、アプリケーションのタイムゾーン要件に応じてDATETIMEまたはTIMESTAMPを選ぶ。
サンプルクエリ
以下は各データ型の例です。
CREATE TABLE events (
event_id INT AUTO_INCREMENT PRIMARY KEY,
event_date DATE,
event_datetime DATETIME,
event_timestamp TIMESTAMP
);
3. 日付の比較方法
基本的な比較演算子の使い方
MySQLでは、日付の比較に以下の演算子を使用します。
=
(等しい)
- 指定した日付と一致するデータを取得します。
SELECT * FROM events WHERE event_date = '2025-01-01';
>
/<
(より大きい/小さい)
- 指定した日付より前後のデータを検索します。
SELECT * FROM events WHERE event_date > '2025-01-01';
<=
/>=
(以上/以下)
- 指定した日付を含む範囲を検索します。
SELECT * FROM events WHERE event_date <= '2025-01-10';
BETWEENを使用した範囲検索
BETWEEN
演算子を使用すると、特定の範囲内の日付を簡単に指定できます。
SELECT * FROM events
WHERE event_date BETWEEN '2025-01-01' AND '2025-01-31';
注意点:
BETWEEN
は範囲の開始値と終了値を含むため、範囲に含まれるデータに漏れがないか確認しましょう。
4. 日付差の計算方法
DATEDIFF関数の使い方
DATEDIFF()
関数を使うと、2つの日付の差(日数)を計算できます。
SELECT DATEDIFF('2025-01-10', '2025-01-01') AS days_difference;
結果:
- 9日
TIMESTAMPDIFF関数の活用
TIMESTAMPDIFF()
を使用すると、年、月、日、時間など任意の単位で差を計算できます。
SELECT TIMESTAMPDIFF(MONTH, '2025-01-01', '2025-12-31') AS months_difference;
結果:
- 11か月
5. 日付の加算・減算
INTERVAL句を使った日付操作
MySQLでは、INTERVAL
句を使用することで、日付に対して加算や減算を簡単に行うことができます。これにより、一定期間前後の日付を取得するクエリを作成できます。
日付の加算
INTERVAL
を使用して日付を加算する例です。
SELECT DATE_ADD('2025-01-01', INTERVAL 7 DAY) AS plus_seven_days;
結果:
2025-01-08
日付の減算
INTERVAL
を使って日付を減算する場合も同様です。
SELECT DATE_SUB('2025-01-01', INTERVAL 1 MONTH) AS minus_one_month;
結果:
2024-12-01
使用例: リマインダーシステム
以下はリマインダー通知を自動で送るために7日前のイベントを取得するクエリ例です。
SELECT event_name, event_date
FROM events
WHERE event_date = DATE_SUB(CURDATE(), INTERVAL 7 DAY);
現在の日付を基準にした計算
CURDATE()
: 現在の日付(年-月-日)を返す。NOW()
: 現在の日時(年-月-日 時:分:秒)を返す。
例: 今日から1週間後の日付を計算。
SELECT DATE_ADD(CURDATE(), INTERVAL 7 DAY) AS next_week;
6. 実践的なクエリ例
特定の日付のレコードを取得
指定された日付に対応するイベントを取得します。
SELECT *
FROM events
WHERE event_date = '2025-01-01';
日付範囲でのデータ抽出
1週間の範囲でイベントを検索する例です。
SELECT *
FROM events
WHERE event_date BETWEEN '2025-01-01' AND '2025-01-07';
日付を基準とした集計
イベントが月ごとに何件登録されているかを集計するクエリです。
SELECT MONTH(event_date) AS event_month, COUNT(*) AS total_events
FROM events
GROUP BY MONTH(event_date);
結果の例:
event_month | total_events |
---|---|
1 | 10 |
2 | 15 |
7. パフォーマンス最適化
インデックスを活用した効率的な検索
日付カラムにインデックスを設定すると、検索速度が大幅に向上します。
インデックスの作成
以下はevent_date
カラムにインデックスを設定するSQLです。
CREATE INDEX idx_event_date ON events(event_date);
インデックスの効果を確認
EXPLAIN
を使用してクエリの実行計画を確認できます。
EXPLAIN SELECT *
FROM events
WHERE event_date = '2025-01-01';
関数使用時の注意点
WHERE
句で関数を使用すると、インデックスが無効になる場合があります。
悪い例
以下のクエリでは、DATE()
関数を使ったためインデックスが利用されません。
SELECT *
FROM events
WHERE DATE(event_date) = '2025-01-01';
改善例
関数を使用せず、直接比較する方法を推奨します。
SELECT *
FROM events
WHERE event_date >= '2025-01-01'
AND event_date < '2025-01-02';

8. FAQ(よくある質問)
Q1: DATE型とDATETIME型の違いは何ですか?
- A1:
- DATE型: 年月日(
YYYY-MM-DD
)のみを保存します。時刻情報は不要な場合に使用します。 - DATETIME型: 年月日と時刻(
YYYY-MM-DD HH:MM:SS
)を保存します。イベントの正確なタイミングが必要な場合に使用します。
例:
CREATE TABLE examples (
example_date DATE,
example_datetime DATETIME
);
Q2: BETWEENで日付範囲を指定する際の注意点は?
- A2:
BETWEEN
は開始日と終了日を含むため、終了日に時間が設定されていない場合、意図したデータを取得できない可能性があります。
例:
-- このクエリでは "2025-01-01 23:59:59" のデータが取得されない場合があります
SELECT *
FROM events
WHERE event_date BETWEEN '2025-01-01' AND '2025-01-31';
改善方法:
終了日に23:59:59を明示的に設定する、または時間を無視した比較を行うと良いです。
SELECT *
FROM events
WHERE event_date >= '2025-01-01' AND event_date < '2025-02-01';
Q3: タイムゾーンの違いはどのように処理しますか?
- A3:
MySQLではTIMESTAMP
型がタイムゾーンに依存します。一方、DATETIME
型は固定値として保存されるため、タイムゾーンの影響を受けません。
タイムゾーンの設定確認例:
SHOW VARIABLES LIKE 'time_zone';
タイムゾーンの変更例:
SET time_zone = '+09:00'; -- 日本標準時 (JST)
Q4: 過去30日間のデータを取得するにはどうすればよいですか?
- A4:
CURDATE()
またはNOW()
とINTERVAL
を組み合わせることで、過去30日間のデータを取得できます。
例:
SELECT *
FROM events
WHERE event_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);
Q5: 日付比較のパフォーマンスを改善する方法は?
- A5:
- インデックスの作成: 日付カラムにインデックスを設定する。
- 関数の使用を避ける:
WHERE
句で関数を使用するとインデックスが無効になる場合があるため、直接比較を使用する。
9. まとめ
記事のポイント
本記事では、MySQLでの日付操作と比較方法について詳しく解説しました。重要なポイントは以下の通りです。
- 日付データ型(DATE、DATETIME、TIMESTAMP)の特徴と使い分け。
- 基本的な比較方法(
=
、>
,<
,BETWEEN
など)。 - 日付差の計算方法(
DATEDIFF()
、TIMESTAMPDIFF()
)。 - パフォーマンス向上のためのインデックス活用と最適なクエリ設計。
この記事を通じて、MySQLでの日付操作を効率的に行い、実用的なクエリを作成するスキルが身につくことを願っています。