【问题标题】:How to select date from datetime column?如何从日期时间列中选择日期?
【发布时间】:2010-12-17 18:51:44
【问题描述】:

我有一个“日期时间”类型的列,其值类似于 2009-10-20 10:00:00

我想从日期时间中提取日期并编写如下查询:

SELECT * FROM 
data 
WHERE datetime = '2009-10-20' 
ORDER BY datetime DESC

以下是最好的方法吗?

SELECT * FROM 
data 
WHERE datetime BETWEEN('2009-10-20 00:00:00' AND '2009-10-20 23:59:59')
ORDER BY datetime DESC

然而,这会返回一个空的结果集。有什么建议吗?

【问题讨论】:

    标签: mysql date datetime


    【解决方案1】:

    可以使用MySQL的DATE()函数:

    WHERE DATE(datetime) = '2009-10-20'
    

    你也可以试试这个:

    WHERE datetime LIKE '2009-10-20%'

    有关使用 LIKE 的性能影响的信息,请参阅 this answer

    【讨论】:

    • 试过这个:DATE(datetime) = '2009-10-20',它可以工作
    • 第一个很慢,忽略了索引。最好有 LIKE 'date%'
    • WHERE DATE(datetime) LIKE '%keyword%' 它的工作原理,谢谢
    • 如果 Rails 时区不是 UTC,我相信这不会按预期工作。这是因为 DATE() 将列值解析为 UTC。因此,如果我们查询“2016-12-30”,我们希望找到的日期如“Fri, 30 Dec 2016 00:00:00 SGT +08:00”将找不到。为什么?因为 DATE() 在进行比较之前会将其解析为等效的 UTC,即“2016-12-29 16:00:00 UTC”。如果我错了,请纠正我,因为直到最近这对我来说也是一个问题。
    • WHERE DATE(datetime) = '{?sdate} 非常适合 Crystal Reports 参数!干得好!
    【解决方案2】:

    使用WHERE DATE(datetime) = '2009-10-20'存在性能问题。如here所述:

    • 它将为所有行计算DATE(),包括那些不匹配的行。
    • 这将使查询无法使用索引。

    使用允许使用索引的BETWEEN><= 运算符:

    SELECT * FROM data 
    WHERE datetime BETWEEN '2009-10-20 00:00:00' AND '2009-10-20 23:59:59'
    

    更新:在索引列中使用LIKE 代替运算符的影响很高。这些是在有 1,176,000 行的表上的一些测试结果:

    • 使用datetime LIKE '2009-10-20%' => 2931ms
    • 使用datetime >= '2009-10-20 00:00:00' AND datetime <= '2009-10-20 23:59:59' => 168ms

    对同一个查询进行第二次调用时,差异会更大:2984 毫秒与 7 毫秒(是的,只有 7 毫秒!)。我在使用 Hibernate 重写项目中的一些旧代码时发现了这一点。

    【讨论】:

    • 有趣的是,如果 MySql 实现自动将 DATE(datetime) 转换为 BETWEEN AND 在场景下我们得到简短的语句和酷炫的性能。为什么不?为什么他们不这样做? :)
    • 因为DATE(datetime) in (:list) 之类的东西不适用于BETWEEN
    【解决方案3】:

    您可以将日期时间格式化为 Y-M-D 部分:

    DATE_FORMAT(datetime, '%Y-%m-%d')
    

    【讨论】:

    • 这样,如果需要,您可以只获取时间部分:DATE_FORMAT(datetime, '%H:%i:%S')
    • 这对格式化日期时间很有用,但作为回报,数据库将返回一个新数组来设置它的名称,只是在末尾添加所需的名称 DATE_FORMAT(columnName, '%Y-%m-% d') arrayName 更多细节检查文档dev.mysql.com/doc/refman/8.0/en/…
    【解决方案4】:

    虽然页面上的所有答案都会返回所需的结果,但它们都存在性能问题。 切勿对 WHERE 子句中的字段执行计算(包括 DATE() 计算),因为必须对表中的所有行执行该计算。

    BETWEEN ... AND 结构包含两种边界条件,要求一个在结束日期指定 23:59:59 语法,这本身有其他问题(微秒事务,我相信 MySQL 在 2009 年不支持问题)。

    查询特定日期的 MySQL timestamp 字段的正确方法是检查所需日期的大于等于,然后检查第二天的小于,不指定小时。

    WHERE datetime>='2009-10-20' AND datetime<'2009-10-21'
    

    这是性能最快、内存最低、资源消耗最少的方法,并且还支持所有 MySQL 功能和极端情况,例如亚秒级时间戳精度。此外,它是面向未来的。

    【讨论】:

    • 并且,使用您的性能参数,是否在表的每一行上同等计算 ">=" 和 "
    • @JavierGuerrero:我的示例比较了两个常量:一个来自表和一个字符串文字。
    • “表中的一个”不是常数,它因每一行而异,因此必须对每一行进行相同的计算(而且,两者都必须转换为纪元时间进行比较)
    【解决方案5】:

    这里是所有格式

    假设这是包含datetime 值的列,表data

    +--------------------+
    | date_created       |
    +--------------------+
    | 2018-06-02 15:50:30|
    +--------------------+
    

    mysql> select DATE(date_created) from data;
    +--------------------+
    | DATE(date_created) |
    +--------------------+
    | 2018-06-02         |
    +--------------------+
    

    mysql> select YEAR(date_created) from data;
    +--------------------+
    | YEAR(date_created) |
    +--------------------+
    |               2018 |
    +--------------------+
    

    mysql> select MONTH(date_created) from data;
    +---------------------+
    | MONTH(date_created) |
    +---------------------+
    |                   6 |
    +---------------------+
    

    mysql> select DAY(date_created) from data;
    +-------------------+
    | DAY(date_created) |
    +-------------------+
    |                 2 |
    +-------------------+
    

    mysql> select HOUR(date_created) from data;
    +--------------------+
    | HOUR(date_created) |
    +--------------------+
    |                 15 |
    +--------------------+
    

    mysql> select MINUTE(date_created) from data;
    +----------------------+
    | MINUTE(date_created) |
    +----------------------+
    |                   50 |
    +----------------------+
    

    mysql> select SECOND(date_created) from data;
    +----------------------+
    | SECOND(date_created) |
    +----------------------+
    |                   31 |
    +----------------------+
    

    【讨论】:

      【解决方案6】:

      你可以使用:

      DATEDIFF ( day , startdate , enddate ) = 0
      

      或者:

      DATEPART( day, startdate ) = DATEPART(day, enddate)
      AND 
      DATEPART( month, startdate ) = DATEPART(month, enddate)
      AND
      DATEPART( year, startdate ) = DATEPART(year, enddate)
      

      或者:

      CONVERT(DATETIME,CONVERT(VARCHAR(12), startdate, 105)) = CONVERT(DATETIME,CONVERT(VARCHAR(12), enddate, 105))
      

      【讨论】:

        【解决方案7】:

        使用日期函数的简单和最佳方式

        例子

        SELECT * FROM 
        data 
        WHERE date(datetime) = '2009-10-20' 
        

        SELECT * FROM 
        data 
        WHERE date(datetime ) >=   '2009-10-20'  && date(datetime )  <= '2009-10-20'
        

        【讨论】:

          【解决方案8】:

          好吧,在声明中使用LIKE 是最好的选择 WHERE datetime LIKE '2009-10-20%' 它应该在这种情况下工作

          【讨论】:

            猜你喜欢
            • 2019-04-04
            • 2013-10-02
            • 2019-03-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-09-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多