【发布时间】:2013-01-24 00:14:00
【问题描述】:
我正在尝试从数据库表中仅选择今天的记录。
目前我使用
SELECT * FROM `table` WHERE (`timestamp` > DATE_SUB(now(), INTERVAL 1 DAY));
但这需要过去 24 小时的结果,我需要它只选择今天的结果,而忽略时间。如何仅根据日期选择结果?
【问题讨论】:
我正在尝试从数据库表中仅选择今天的记录。
目前我使用
SELECT * FROM `table` WHERE (`timestamp` > DATE_SUB(now(), INTERVAL 1 DAY));
但这需要过去 24 小时的结果,我需要它只选择今天的结果,而忽略时间。如何仅根据日期选择结果?
【问题讨论】:
使用DATE 和CURDATE()
SELECT * FROM `table` WHERE DATE(`timestamp`) = CURDATE()
警告!此查询没有有效地使用索引。如需更有效的解决方案,请参阅answer below
【讨论】:
Using where; Using index 的价值?
timestamp(和我的情况下的date)是MySQL 保留字
只需将其转换为日期:
SELECT * FROM `table` WHERE CAST(`timestamp` TO DATE) == CAST(NOW() TO DATE)
【讨论】:
如果您希望使用索引并且查询不进行表扫描:
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) = ?
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 <= ? 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
它使用对索引的范围扫描,然后只从表中读取相应的行。
【讨论】:
INDEX t_IX (timestamp, id) 可以(应该?)只是INDEX t_IX (timestamp),因为索引中隐含了主键。还是有我不明白这样做的原因?我在 sql-fiddle 中尝试过,看到了相同(更好)的执行计划
id(因为它是 PK,因此是表的聚集索引)无论如何都会附加到索引中。因此,显式添加它并没有什么坏处(它可能会捕获一些优化器盲点)。在这种情况/查询中肯定不相关。
timestamp < CURDATE() + INTERVAL 1 DAY 是必要的?
SELECT * FROM `table` WHERE timestamp >= CURDATE()
比较短,不用'AND timestamp
因为 CURDATE() 总是返回当前日期
【讨论】:
我们可以用多少种方法给这只猫剥皮?这是另一个变体。
SELECT * FROM table WHERE DATE(FROM_UNIXTIME(timestamp)) = '2015-11-18';
【讨论】:
我认为这可能是最简单的:
SELECT * FROM `table` WHERE `timestamp` like concat(CURDATE(),'%');
【讨论】:
如果你想和一个特定的日期进行比较,你可以直接写成这样:
select * from `table_name` where timestamp >= '2018-07-07';
// 这里时间戳是类型为时间戳的列的名称
或
为了获取今天的日期,可以使用 CURDATE() 函数,所以:
select * from `table_name` where timestamp >= CURDATE();
【讨论】:
在 Visual Studio 2017 上,使用内置数据库进行开发我遇到了当前给定解决方案的问题,我不得不更改代码以使其正常工作,因为它抛出了 DATE() 不是内置函数的错误.
这是我的解决方案:
where CAST(TimeCalled AS DATE) = CAST(GETDATE() AS DATE)
【讨论】:
或者您可以使用 CURRENT_DATE 替代方法,结果相同:
SELECT * FROM yourtable WHERE created >= CURRENT_DATE
【讨论】:
SELECT * FROM table WHERE FROM_UNIXTIME(your_column_with_unix_time,'%Y-%m-%d') = CURDATE()
【讨论】: