MySQLで前日(昨日)のレコードをすべて取得する方法
はじめに
MySQLでテーブルから「昨日」の日付に該当するレコードをすべて取得したいケースは、ログ集計や日次レポートの作成などでよく発生します。本記事では、DATE()関数とNOW()関数、INTERVALを組み合わせた基本的な方法を、実際のSQL例とともにわかりやすく解説します。
基本構文
前日のレコードを取得するには、以下のような構文を使用します。
SELECT * FROM テーブル名 WHERE DATE(カラム名) = DATE(NOW() - INTERVAL 1 DAY);
ポイントは、DATETIME型のカラムに対してDATE()関数を適用し、時刻部分を切り捨てて「日付」として比較している点です。NOW() - INTERVAL 1 DAYで現在日時の1日前を求め、さらにDATE()で日付のみに変換することで、昨日の0時00分00秒〜23時59分59秒までのレコードがすべて一致します。
サンプルテーブルの作成
それでは、実際の動きを確認してみましょう。まずはサンプル用のテーブルを作成します。
mysql> CREATE TABLE yesterDayRecordsDemo
-> (
-> Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> ArrivalDateTime datetime
-> );
Query OK, 0 rows affected (0.44 sec)
テストデータの挿入
続いて、INSERT文を使っていくつかのレコードを挿入します。意図的に異なる日付のデータを混ぜておくことで、絞り込みの効果が確認しやすくなります。
mysql> INSERT INTO yesterDayRecordsDemo(ArrivalDateTime) VALUES('2014-11-09 13:45:21');
Query OK, 1 row affected (0.11 sec)
mysql> INSERT INTO yesterDayRecordsDemo(ArrivalDateTime) VALUES('2017-10-19 11:41:31');
Query OK, 1 row affected (0.15 sec)
mysql> INSERT INTO yesterDayRecordsDemo(ArrivalDateTime) VALUES('2019-02-25 10:40:45');
Query OK, 1 row affected (0.14 sec)
mysql> INSERT INTO yesterDayRecordsDemo(ArrivalDateTime) VALUES('2019-02-26 12:06:07');
Query OK, 1 row affected (0.15 sec)
mysql> INSERT INTO yesterDayRecordsDemo(ArrivalDateTime) VALUES('2019-02-25 12:06:47');
Query OK, 1 row affected (0.19 sec)
mysql> INSERT INTO yesterDayRecordsDemo(ArrivalDateTime) VALUES('2019-02-27 11:45:49');
Query OK, 1 row affected (0.12 sec)
登録済みレコードの確認
SELECT文ですべてのレコードを表示してみます。
mysql> SELECT * FROM yesterDayRecordsDemo;
実行結果は以下の通りです。
+----+---------------------+ | Id | ArrivalDateTime | +----+---------------------+ | 1 | 2014-11-09 13:45:21 | | 2 | 2017-10-19 11:41:31 | | 3 | 2019-02-25 10:40:45 | | 4 | 2019-02-26 12:06:07 | | 5 | 2019-02-25 12:06:47 | | 6 | 2019-02-27 11:45:49 | +----+---------------------+ 6 rows in set (0.00 sec)
ここでは、現在の日付が「2019-02-27」であると仮定します。この場合、前日に該当するのは「2019-02-26」のレコードです。
前日のレコードを取得するクエリ
いよいよ、昨日のレコードだけを抽出するクエリを実行します。
mysql> SELECT * FROM yesterDayRecordsDemo
WHERE DATE(ArrivalDateTime) = DATE(NOW() - INTERVAL 1 DAY);
実行結果:
+----+---------------------+ | Id | ArrivalDateTime | +----+---------------------+ | 4 | 2019-02-26 12:06:07 | +----+---------------------+ 1 row in set (0.08 sec)
Id=4の「2019-02-26 12:06:07」だけが取得できました。時刻が昼間であっても、日付が前日であれば正しくヒットすることが確認できます。
別の書き方:CURDATE()を使う方法
NOW()の代わりにCURDATE()(またはCURRENT_DATE)を使えば、より直感的に記述することもできます。
SELECT * FROM yesterDayRecordsDemo WHERE DATE(ArrivalDateTime) = CURDATE() - INTERVAL 1 DAY;
CURDATE()は現在の日付のみを返すため、「今日の日付 − 1日 = 昨日」という計算がシンプルに行えるのがメリットです。
パフォーマンスに関する注意点
DATE(カラム名)のようにカラム側に関数を適用すると、インデックスが存在しても通常のインデックス検索が利用されにくくなることがあります。レコード件数が多いテーブルでは、範囲条件に書き換えることで高速化が期待できます。
SELECT * FROM yesterDayRecordsDemo WHERE ArrivalDateTime >= CURDATE() - INTERVAL 1 DAY AND ArrivalDateTime < CURDATE();
この書き方は「昨日の0時以降〜今日の0時未満」という範囲指定になっており、カラム側に関数を使わないためインデックスを有効活用できます。大量データを扱う場合は、こちらの形式を推奨します。
まとめ
- 前日のレコード取得の基本形は
WHERE DATE(カラム名) = DATE(NOW() - INTERVAL 1 DAY) CURDATE() - INTERVAL 1 DAYを使った書き方も可能- 大量データの場合は範囲条件(>= と <)に書き換えるとインデックスが効きやすい
-
MySQLで1つのクエリを使って最初のテーブルから2つ目のテーブルへ一部のレコードのみを挿入する方法
MySQLでは、INSERT INTO ... SELECT構文(ネストされた挿入)を利用することで、あるテーブルから別のテーブルへレコードをコピーできます。さらにWHERE句で条件を指定すれば、すべてではなく一部のレコードだけを挿入することも可能です。基本構文INSERT INTO テーブル名2(カラム名1, カラム名2, .....N)SELECT カラム名1, カラム名2, ....N FROM テーブル名1 WHERE 条件;それでは、実際に例を見ながら確認していきましょう。サンプルテーブルの作成まず、元となるテーブルを作成します。mysql> create table Demo
-
【MySQL】UNION ALLを使って複数テーブルのCOUNT合計を1つのクエリで取得する方法
はじめにMySQLでは、複数のテーブルに保存されたデータの件数(COUNT)をまとめて集計したいケースがあります。そんなときに便利なのがUNION ALLです。UNION ALLを使えば、複数のSELECT文の結果を1つに結合し、その合計値を単一のクエリで取得できます。本記事では、サンプルテーブルを作成しながら、具体的な手順をわかりやすく解説します。1つ目のテーブルを作成するまず、以下のCREATE TABLE文で最初のテーブル「DemoTable1」を作成します。mysql> create table DemoTable1-> (-> Id int,-> Name v