Skip to main content
4 of 5
fix bad data
Rick James
  • 79.4k
  • 5
  • 51
  • 117

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.

Rick James
  • 79.4k
  • 5
  • 51
  • 117