Давайте создадим несколько тестовых данных:
mysql> create table t (id int auto_increment, stamp datetime, primary key (id));
Query OK, 0 rows affected (0.46 sec)
mysql> insert into t (stamp) values
-> ('2018-09-24 18:59:59'), ('2018-09-24 19:00:00'), ('2018-09-24 19:00:01'),
-> ('2018-09-25 06:59:59'), ('2018-09-25 07:00:00'), ('2018-09-25 07:00:01'),
-> ('2018-09-25 18:59:59'), ('2018-09-25 19:00:00'), ('2018-09-25 19:00:01'),
-> ('2018-09-26 06:59:59'), ('2018-09-26 07:00:00'), ('2018-09-26 07:00:01'),
-> ('2018-09-26 18:59:59'), ('2018-09-26 19:00:00'), ('2018-09-26 19:00:01'),
-> ('2018-09-27 06:59:59'), ('2018-09-27 07:00:00'), ('2018-09-27 07:00:01');
Query OK, 18 rows affected (0.00 sec)
Records: 18 Duplicates: 0 Warnings: 0
mysql> select * from t;
+----+---------------------+
| id | stamp |
+----+---------------------+
| 1 | 2018-09-24 18:59:59 |
| 2 | 2018-09-24 19:00:00 |
| 3 | 2018-09-24 19:00:01 |
| 4 | 2018-09-25 06:59:59 |
| 5 | 2018-09-25 07:00:00 |
| 6 | 2018-09-25 07:00:01 |
| 7 | 2018-09-25 18:59:59 |
| 8 | 2018-09-25 19:00:00 |
| 9 | 2018-09-25 19:00:01 |
| 10 | 2018-09-26 06:59:59 |
| 11 | 2018-09-26 07:00:00 |
| 12 | 2018-09-26 07:00:01 |
| 13 | 2018-09-26 18:59:59 |
| 14 | 2018-09-26 19:00:00 |
| 15 | 2018-09-26 19:00:01 |
| 16 | 2018-09-27 06:59:59 |
| 17 | 2018-09-27 07:00:00 |
| 18 | 2018-09-27 07:00:01 |
+----+---------------------+
18 rows in set (0.00 sec)
Теперь мы хотим выбрать из 2018-09-24 19:00:00
до 2018-09-25 07:00:00
:
mysql> select * from t where stamp between (@start := '2018-09-24 19:00:00') and date_add(@start, interval 12 hour);
+----+---------------------+
| id | stamp |
+----+---------------------+
| 2 | 2018-09-24 19:00:00 |
| 3 | 2018-09-24 19:00:01 |
| 4 | 2018-09-25 06:59:59 |
| 5 | 2018-09-25 07:00:00 |
+----+---------------------+
4 rows in set (0.01 sec)
Если мы хотим включить 3 дняЦенность данных во время этих окон, мы можем сделать это, используя UNION ALL
:
mysql> select * from t where stamp between (@start := '2018-09-24 19:00:00') and date_add(@start, interval 12 hour)
-> union all select * from t where stamp between (@start := '2018-09-25 19:00:00') and date_add(@start, interval 12 hour)
-> union all select * from t where stamp between (@start := '2018-09-26 19:00:00') and date_add(@start, interval 12 hour);
+----+---------------------+
| id | stamp |
+----+---------------------+
| 2 | 2018-09-24 19:00:00 |
| 3 | 2018-09-24 19:00:01 |
| 4 | 2018-09-25 06:59:59 |
| 5 | 2018-09-25 07:00:00 |
| 8 | 2018-09-25 19:00:00 |
| 9 | 2018-09-25 19:00:01 |
| 10 | 2018-09-26 06:59:59 |
| 11 | 2018-09-26 07:00:00 |
| 14 | 2018-09-26 19:00:00 |
| 15 | 2018-09-26 19:00:01 |
| 16 | 2018-09-27 06:59:59 |
| 17 | 2018-09-27 07:00:00 |
+----+---------------------+
12 rows in set (0.00 sec)
И вот как это делается.
Отредактировано, чтобы добавить: После просмотра ответа Ника, который использует TIME()
это действительно более чистое решение:
mysql> select * from t where date(stamp) between '2018-09-24' and '2018-09-27'
-> and time(stamp + interval 12 hour) between '07:00:00' and '19:00:00';
+----+---------------------+
| id | stamp |
+----+---------------------+
| 2 | 2018-09-24 19:00:00 |
| 3 | 2018-09-24 19:00:01 |
| 4 | 2018-09-25 06:59:59 |
| 5 | 2018-09-25 07:00:00 |
| 8 | 2018-09-25 19:00:00 |
| 9 | 2018-09-25 19:00:01 |
| 10 | 2018-09-26 06:59:59 |
| 11 | 2018-09-26 07:00:00 |
| 14 | 2018-09-26 19:00:00 |
| 15 | 2018-09-26 19:00:01 |
| 16 | 2018-09-27 06:59:59 |
| 17 | 2018-09-27 07:00:00 |
+----+---------------------+
12 rows in set (0.00 sec)