LoginSignup
1
0

More than 1 year has passed since last update.

LaravelのDBの日付関連メソッド

Posted at

Laravelの日付関連メソッド

データ準備

下記SQLを実行し、userテーブルを作成する

CREATE TABLE `test_user`(
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(128) NOT NULL,
  `registered_date` INT UNSIGNED NOT NULL,
  `created_at` DATETIME NOT NULL,
  `updated_at` DATETIME NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_test_user_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULR CHARSET=utf8mb4;

whereDate

// created_at(datetime型)のカラムが2021-11-01のレコードを取得する
User::whereDate('created_at', '2021-11-01')->get();

// 実際のクエリを確認する
User::whereDate('created_at', '2021-11-01')->toSql();
// SELECT * FROM user WHERE DATE('created_at') = '2021-11-01';

EXPLAINを実行してみると、created_atにはったインデックスは使われていない。

mysql> EXPLAIN SELECT * FROM test_user WHERE DATE(`created_at`) = '2021-11-27';
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test_user | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

whereMonth

// created_at(datetime型)が11月のレコードを取得する
User::whereMonth('created_at', '11')->get();

// 実際のクエリを確認する
User::whereMonth('created_at', '11')->toSql();
// SELECT * FROM user WHERE MONTH(`created_at`) = '11';

EXPLAINを実行してみると、created_atにはったインデックスは使われていない。

mysql> EXPLAIN SELECT * FROM test_user WHERE MONTH(`created_at`) = '11';
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test_user | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

whereDay

// created_at(datetime型)が1日のレコードを取得する
User::whereDay('created_at', '01')->get();

// 実際のクエリを確認する
User::whereDay('created_at', '01')->toSql();
// SELECT * FROM user WHERE DAY(`created_at`) = 1;

EXPLAINを実行してみると、created_atにはったインデックスは使われていない。

mysql> EXPLAIN SELECT * FROM `test_user` WHERE DAY(`created_at`) = 1;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test_user | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

whereYear

// created_at(datetime型)が2021年のレコードを取得する
User::whereYear('created_at', '2021')->get();

// 実際のクエリを確認する
User::whereYear('created_at', '2021')->toSql();
// SELECT * FROM user WHERE YEAR(`created_at`) = 2021;

EXPLAINを実行してみると、created_atにはったインデックスは使われていない。

mysql> EXPLAIN SELECT * FROM `test_user` WHERE YEAR(`created_at`) = 2021;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test_user | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

whereTime

// created_at(datetime型)が14:29:57のレコードを取得する
User::whereYear('created_at', '14:29:57')->get();

// 実際のクエリを確認する
User::whereTime('created_at', '14:29:57')->toSql();
// SELECT * FROM user WHERE TIME(`created_at`) = '14:29:57';

EXPLAINを実行してみると、created_atにはったインデックスは使われていない。

mysql> EXPLAIN SELECT * FROM `test_user` TIME(`created_at`) = '14:29:57';
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test_user | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

まとめ

いずれの場合もカラムを変換しているため、インデックスを貼っていてもこれらのメソッドを使う場合はインデックスが使われないことが分かった。
パフォーマンス重視しない分析等で使用できたらいいかな。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0