【问题标题】:How to select rows that have current day's timestamp?如何选择具有当天时间戳的行?
【发布时间】:2013-01-24 00:14:00
【问题描述】:

我正在尝试从数据库表中仅选择今天的记录。

目前我使用

SELECT * FROM `table` WHERE (`timestamp` > DATE_SUB(now(), INTERVAL 1 DAY));

但这需要过去 24 小时的结果,我需要它只选择今天的结果,而忽略时间。如何仅根据日期选择结果?

【问题讨论】:

    标签: mysql sql timestamp


    【解决方案1】:

    使用DATECURDATE()

    SELECT * FROM `table` WHERE DATE(`timestamp`) = CURDATE()
    

    警告!此查询没有有效地使用索引。如需更有效的解决方案,请参阅answer below

    see the execution plan on the DEMO

    【讨论】:

    • 查看区别:SQL-Fiddle 注意第二个查询中的 FILTERED = 25。
    • @ypercube 哦,我错过了,但我想知道为什么额外 Using where; Using index 的价值?
    • 索引用于选择行。但是使用您的查询扫描整个索引(并使用 DATE() 转换所有值以评估条件)。我会用一个更好的例子来更新我的答案。
    • 恕我直言,ypercube 解决方案出于性能原因更好,如果您的表有数十万行,您绝对应该朝这个方向发展
    • `` 很重要,因为timestamp(和我的情况下的date)是MySQL 保留字
    【解决方案2】:

    只需将其转换为日期:

    SELECT * FROM `table` WHERE CAST(`timestamp` TO DATE) == CAST(NOW() TO DATE)
    

    【讨论】:

      【解决方案3】:

      如果您希望使用索引并且查询不进行表扫描:

      WHERE timestamp >= CURDATE()
        AND timestamp < CURDATE() + INTERVAL 1 DAY
      

      为了显示这对实际执行计划的影响,我们将使用 SQL-Fiddle(一个非常有用的网站)进行测试:

      CREATE TABLE test                            --- simple table
          ( id INT NOT NULL AUTO_INCREMENT
          ,`timestamp` datetime                    --- index timestamp
          , data VARCHAR(100) NOT NULL 
                DEFAULT 'Sample data'
          , PRIMARY KEY (id)
          , INDEX t_IX (`timestamp`, id)
          ) ;
      
      INSERT INTO test
          (`timestamp`)
      VALUES
          ('2013-02-08 00:01:12'),
          ---                                      --- insert about 7k rows
          ('2013-02-08 20:01:12') ;
      

      现在让我们试试这两个版本。


      带有 DATE(timestamp) = ?

      的版本 1
      EXPLAIN
      SELECT * FROM test 
      WHERE DATE(timestamp) = CURDATE()            ---  using DATE(timestamp)
      ORDER BY timestamp ;
      

      说明:

      ID  SELECT_TYPE  TABLE  TYPE  POSSIBLE_KEYS  KEY  KEY_LEN  REF 
      1   SIMPLE       test   ALL
      
      ROWS  FILTERED  EXTRA
      6671  100       Using where; Using filesort
      

      过滤所有 (6671) 行,然后进行文件排序(这不是问题,因为返回的行很少)


      带有 timestamp &lt;= ? AND timestamp &lt; ?

      的版本 2
      EXPLAIN
      SELECT * FROM test 
      WHERE timestamp >= CURDATE()
        AND timestamp < CURDATE() + INTERVAL 1 DAY
      ORDER BY timestamp ;
      

      说明:

      ID  SELECT_TYPE  TABLE  TYPE  POSSIBLE_KEYS  KEY  KEY_LEN  REF 
      1   SIMPLE       test   range t_IX           t_IX    9 
      
      ROWS  FILTERED  EXTRA
      2     100       Using where
      

      它使用对索引的范围扫描,然后只从表中读取相应的行。

      【讨论】:

      • 很好的解释,感谢 sql-fiddle。对您的架构的一条评论让我看了一会儿,INDEX t_IX (timestamp, id) 可以(应该?)只是INDEX t_IX (timestamp),因为索引中隐含了主键。还是有我不明白这样做的原因?我在 sql-fiddle 中尝试过,看到了相同(更好)的执行计划
      • @natbro 是的,如果表使用 InnoDB 引擎,id(因为它是 PK,因此是表的聚集索引)无论如何都会附加到索引中。因此,显式添加它并没有什么坏处(它可能会捕获一些优化器盲点)。在这种情况/查询中肯定不相关。
      • 谁能解释为什么timestamp &lt; CURDATE() + INTERVAL 1 DAY 是必要的?
      • @Nightwolf 因为您可能将行存储在未来时间戳值的位置。该问题要求“仅今天的记录”
      • @TypoCubeᵀᴹ 啊哈,没有考虑到这一点,纯粹是因为时间戳不会做未来的日期。尽管如此,请牢记这一点。
      【解决方案4】:
      SELECT * FROM `table` WHERE timestamp >= CURDATE()
      

      比较短,不用'AND timestamp

      因为 CURDATE() 总是返回当前日期

      MySQL CURDATE() Function

      【讨论】:

      • a) 该问题要求“仅今天的记录”,并且您的代码还获得未来的日期。 b)您的比较不起作用,您必须使用 DATE(timestamp) 进行比较。换句话说:如果您修复了答案,您将获得@JohnWoo 原始答案。
      • 写起来“更短”,但整个世界执行起来更慢
      【解决方案5】:

      我们可以用多少种方法给这只猫剥皮?这是另一个变体。

      SELECT * FROM table WHERE DATE(FROM_UNIXTIME(timestamp)) = '2015-11-18';

      【讨论】:

        【解决方案6】:

        我认为这可能是最简单的:

        SELECT * FROM `table` WHERE `timestamp` like concat(CURDATE(),'%');
        

        【讨论】:

          【解决方案7】:

          如果你想和一个特定的日期进行比较,你可以直接写成这样:

          select * from `table_name` where timestamp >= '2018-07-07';
          

          // 这里时间戳是类型为时间戳的列的名称

          为了获取今天的日期,可以使用 CURDATE() 函数,所以:

          select * from `table_name` where timestamp >=  CURDATE();
          

          【讨论】:

            【解决方案8】:

            在 Visual Studio 2017 上,使用内置数据库进行开发我遇到了当前给定解决方案的问题,我不得不更改代码以使其正常工作,因为它抛出了 DATE() 不是内置函数的错误.

            这是我的解决方案:

            where CAST(TimeCalled AS DATE) = CAST(GETDATE() AS DATE)

            【讨论】:

            • 您可能没有使用 MySQL,而是使用了其他一些 DBMS(可能是 SQL Server?)注意问题的标签。
            【解决方案9】:

            或者您可以使用 CURRENT_DATE 替代方法,结果相同:

            SELECT * FROM yourtable WHERE created >= CURRENT_DATE
            

            Examples from database.guide

            【讨论】:

              【解决方案10】:
              SELECT * FROM table WHERE FROM_UNIXTIME(your_column_with_unix_time,'%Y-%m-%d') = CURDATE()
              

              【讨论】:

                猜你喜欢
                • 2021-10-31
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多