MySQL将DATE字符串与DATETIME字段中的字符串进行比较

Man*_*era 84 mysql comparison datetime

我有一个问题:是否可以通过将一个DATE字符串"2010-04-29"与存储为DATETIME(2010-04-29 10:00)的字符串进行比较来从MySQL数据库中进行选择?

我有一个过滤数据的日期选择器,我想通过DATETIME字段查询表,如下所示:

SELECT * FROM `calendar` WHERE startTime = '2010-04-29'"
Run Code Online (Sandbox Code Playgroud)

...我希望得到DATETIME值为"2010-04-29 10:00"的行.

有什么建议?谢谢.

Dav*_*vid 146

使用以下内容:

SELECT * FROM `calendar` WHERE DATE(startTime) = '2010-04-29'
Run Code Online (Sandbox Code Playgroud)

仅供参考,我有一个200万的记录表,我运行了类似的查询.Salils的回答耗时4.48秒,上述耗时2.25秒.

所以,如果表是大的,我会建议这样做.

  • 第一个答案是如此缓慢,因为它必须在比较之前将每个日期时间格式化为字符串.你的更好,因为它只直接比较字段中的日期部分,但它仍然不能使用索引(在mysql 5.1上测试) (6认同)
  • 如果性能是一个问题,则可能值得考虑单独存储日期和时间部分,以便可以将 INDEX 放置在日期部分上。 (2认同)
  • 如果“startTime”已建立索引,则此查询将无法使用索引。 (2认同)

小智 32

如果要选择DATETIME列的DATE部分与某个文字匹配的所有行,则不能这样做:

WHERE startTime = '2010-04-29'
Run Code Online (Sandbox Code Playgroud)

因为MySQL无法直接比较DATE和DATETIME.MySQL做了什么,它使用时间'00:00:00'扩展给定的DATE文字.所以你的状况就变了

WHERE startTime = '2010-04-29 00:00:00'
Run Code Online (Sandbox Code Playgroud)

当然不是你想要的!

条件是一个范围,因此它应该作为范围给出.有几种可能性:

WHERE startTime BETWEEN '2010-04-29 00:00:00' AND '2010-04-29 23:59:59'
WHERE startTime >= '2010-04-29' AND startTime < ('2010-04-29' + INTERVAL 1 DAY)
Run Code Online (Sandbox Code Playgroud)

第一个错误的可能性很小 - 当你的DATETIME列使用亚秒级分辨率并且在23:59:59 + epsilon预约时.一般来说,我建议使用第二种变体.

两种变体都可以在startTime上使用索引,这在表增长时将变得很重要.

  • 大卫的版本不好,它不能使用索引.要使用索引,你必须直接过滤列,而不是函数的结果(`date()`,`year()`,`datediff()`或任何类似的) (8认同)

Sal*_*lil 23

SELECT * FROM `calendar` WHERE DATE_FORMAT(startTime, "%Y-%m-%d") = '2010-04-29'"
Run Code Online (Sandbox Code Playgroud)

要么

SELECT * FROM `calendar` WHERE DATE(startTime) = '2010-04-29'
Run Code Online (Sandbox Code Playgroud)

  • 这是一个糟糕的查询.不惜一切代价避免这样做.如果startTime上有索引,则此查询不能使用它,因为它将一个函数应用于列而不是直接使用它.这意味着任何这样的查询都需要全表扫描.在大型表上,这将意味着极慢的查询. (22认同)
  • @CarlosAlbertoMartínezGadea 这个版本很慢,因为它必须在比较之前将每个值格式化为字符串...大卫的版本不需要它,但仍然无法使用索引,因此不是最佳的。有关可以使用索引的版本,请参阅 XL_ 的答案。不幸的是,没有更好的方法可以在 mysql 中正确执行此操作 (2认同)