Don't use BETWEEN
for checking a date or datetime range; it is inclusive, so you get the second (usually midnight) at both ends.
For checking DATE or DATETIME against one "day", do this:
WHERE col >= '2019-12-19'
AND col < '2019-12-19' + INTERVAL 1 DAY
That will work 'correctly' whether col
is a DATE, DATETIME, or DATETIME(6). And the Optimizer is generally happy with that expression.
Also, keep in mind that CURDATE()
is midnight of this morning.
(Rebuttal to ypercube:)
Perhaps this demonstrates that the issue is with the datatype returned by COALESCE
, not the existence of 00:00:00
:
mysql> SELECT dt FROM dtts WHERE COALESCE(dt, '9999-1-1')
between '2016-07-31' and '2016-07-31';
Empty set (0.00 sec)
mysql> SELECT dt, just_date FROM dtts WHERE COALESCE(dt, DATE('9999-1-1'))
between '2016-07-31' and '2016-07-31';
+---------------------+------------+
| dt | just_date |
+---------------------+------------+
| 2016-07-31 00:00:00 | 2016-07-31 |
| 2016-07-31 00:00:00 | 2016-07-31 |
| 2016-07-31 00:00:00 | 2016-07-31 |
| 2016-07-31 00:00:00 | 2016-07-31 |
| 2016-07-31 00:00:00 | 2016-07-31 |
+---------------------+------------+
5 rows in set (0.00 sec)
mysql> SELECT dt, just_date FROM dtts WHERE COALESCE(just_date, '9999-1-1')
between '2016-07-31' and '2016-07-31';
+---------------------+------------+
| dt | just_date |
+---------------------+------------+
| 2016-07-31 00:00:00 | 2016-07-31 |
| 2016-07-31 00:00:00 | 2016-07-31 |
| 2016-07-31 00:00:00 | 2016-07-31 |
| 2016-07-31 00:00:00 | 2016-07-31 |
| 2016-07-31 00:00:00 | 2016-07-31 |
+---------------------+------------+
mysql> SELECT dt, just_date FROM dtts WHERE COALESCE(just_date, '9999-1-1')
between '2016-07-31 00:00:00' and '2016-07-31 00:00:00';
Empty set (0.00 sec)
Perhaps if the non-null arguments of COALESCE
have different datatypes, then there is a pecking order, something like INT > string > datetime. I found this for including INT.