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


104

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

目前我使用

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

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

Answers:


191

使用DATECURDATE()

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

我想使用DATE 仍然使用INDEX

在演示中查看执行计划


看到不同之处:SQL-Fiddle注意第二个查询中的FILTERED = 25。
ypercubeᵀᴹ

@ypercube哦,我错过了,但是我想知道为什么额外的价值Using where; Using index
John Woo,

1
索引用于选择行。但是查询会扫描整个索引(并且所有值都将通过DATE()进行转换以评估条件)。我将用一个更好的例子来更新我的答案。
ypercubeᵀᴹ

1
出于所有应有的尊重,出于性能方面的考虑,ypercube解决方案更好,如果您的表有成千上万的行,则您绝对应该朝这个方向前进
Vincent

1
之所以很重要,是因为timestamp(和date我的情况一样)是MySQL保留字
Victor Ferreira 2015年

55

如果要使用索引并且查询不执行表扫描:

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') ;

现在让我们尝试2个版本。


版本1与 DATE(timestamp) = ?

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)行,然后进行文件排序(这不成问题,因为返回的行很少)


版本2 timestamp <= ? AND timestamp < ?

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

1
@natbro是的,如果表使用InnoDB引擎,则id(因为它是PK,因此是表的聚集索引)(无论如何)都将附​​加在索引中。因此,显式添加它没有什么坏处(它可能会遇到一些优化器盲点)。在这种情况/查询中,这当然是不相关的。
ypercubeᵀᴹ

谁能解释为什么timestamp < CURDATE() + INTERVAL 1 DAY有必要?
Nightwolf

@Nightwolf,因为您可能在将来的时间戳值所在的地方存储了行。这个问题要求“仅今天的记录”
ypercubeᵀᴹ

@TypoCubeᵀᴹ啊哈,不是纯粹出于时间戳而不考虑未来日期的考虑。尽管如此,请记住好点。
Nightwolf

11
SELECT * FROM `table` WHERE timestamp >= CURDATE()

它更短,不需要使用“ AND timestamp <CURDATE()+ INTERVAL 1 DAY”

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

MySQL CURDATE()函数


a)该问题要求“仅今天的记录”,并且您的代码还会获得将来的日期。b)您的比较不起作用,必须使用DATE(timestamp)来完成。换句话说:如果您解决了问题,您将获得@JohnWoo原始答案。
Katapofatico

2

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

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


2

如果要与特定日期进行比较,可以直接将其写为:

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

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

要么

要获取今天的日期,可以使用CURDATE()函数,因此:

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

1

只需将其转换为日期即可:

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



0

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

这是我的解决方案:

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


您可能不是在使用MySQL,而是在使用其他一些DBMS(也许是SQL Server?)。请注意问题的标签。
ypercubeᵀᴹ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.