如何选择具有当天时间戳的行?

Posted

技术标签:

【中文标题】如何选择具有当天时间戳的行?【英文标题】: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 小时的结果,我需要它只选择今天的结果,而忽略时间。如何仅根据日期选择结果?

【问题讨论】:

【参考方案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()

【讨论】:

以上是关于如何选择具有当天时间戳的行?的主要内容,如果未能解决你的问题,请参考以下文章

如何选择每个项目具有最大时间戳的行集?

如何为每个键值选择具有最新时间戳的行?

用于从表中选择具有最新时间戳的行的 JOOQ 代码

SQL - 如何选择具有最大值列的行

如何从具有最后时间戳的数据框中选择不同的记录

如何选择小于时间戳的日期和时间?