我的SQL中的WHERE DATEDIFF有问题

时间:2013-01-15 21:54:39

标签: mysql sql datetime

我想我错了。我希望在PHP中提取数据库中不到一天的行。我正在使用Laravel,但那不相关。这就是我所拥有的:

if ($day == 'today') {
    $date = date('Y-m-d H:i:s');
} elseif ($day == 'yesterday') {
    $date = date('Y-m-d H:i:s', strtotime('yesterday'));
} else {
    ...
}

$sql = "SELECT * FROM all_forms_main_contact WHERE DATEDIFF(timestamp, '" . $date . "') <= 1";
$mc = DB::select($sql);
return json_encode($mc);

然而,这并不是正确的结果。这是超过一天的返回结果。

5 个答案:

答案 0 :(得分:3)

这实际上取决于你如何定义“不到一天的时间”。

MySQL DATEDIFF函数仅考虑日期时间值的日期部分,并返回整数天的差异。以下两个查询都将返回值1,表示“1天”,其中一个是8小时的差异,另一个是46小时的差异:

SELECT DATEDIFF('2013-01-15 07:00','2013-01-14 23:00') AS 8_hrs
SELECT DATEDIFF('2013-01-15 23:00','2013-01-14 01:00') AS 46_hrs

因此,完全有可能并且预计查询可能会返回“超过24小时”的行。

(作为DATEDIFF函数的参数提供的文字的hh:mi:ss时间部分被忽略,时间戳值的时间部分被忽略。你只需提供相同的结果即可得到相同的结果YYYY-MM-DD值。)


另请注意,DATEDIFF函数的谓词不可思议,即MySQL无法对索引进行范围扫描以满足该谓词。

为了获得最佳性能,我们通常更喜欢裸列上的等效谓词,例如

WHERE `timestamp` >= expr

使优化器至少可以考虑对timestamp列上的索引使用范围扫描。

如果您正在寻找不到1天的行(意味着不到24小时,或者小于86400秒),分辨率高达一秒,您可以使用谓词之一:

WHERE `timestamp` >= '2013-01-15 16:10' + INTERVAL -1 DAY
WHERE `timestamp` >= '2013-01-15 16:10' + INTERVAL -24 HOUR
WHERE `timestamp` >= '2013-01-15 16:10' + INTERVAL -86400 SECOND

DATE_ADD函数是等效的:

WHERE `timestamp` >= DATE_ADD('2013-01-15 16:10',INTERVAL -1 DAY)

另请注意,没有必要将当前日期值作为SQL文本中的文字传递; MySQL提供了内置函数,可以从MySQL服务器返回当前日期和时间,例如NOW()CURRENT_DATE()SYSDATE()

对于小于24小时或48小时的行:

WHERE `timestamp` >= DATE_ADD(NOW(),INTERVAL -1 DAY)
WHERE `timestamp` >= DATE_ADD(NOW(),INTERVAL -2 DAY)

答案 1 :(得分:1)

此查询选择比-24小时更新的行 例如,如果是04:00 AM,则返回所有行&gt; =昨天04:00 AM:

SELECT * FROM `tbl` WHERE `datetime` >= NOW() - INTERVAL 1 DAY

同样适用于-48小时以上 例如,如果是04:00 AM,则返回所有行&gt; =前一天凌晨04:00:

SELECT * FROM `tbl` WHERE `datetime` >= NOW() - INTERVAL 2 DAY

此查询选择今天的行 例如,如果是04:00 AM,则返回所有行&gt; =今天00:00 AM:

SELECT * FROM `tbl` WHERE `datetime` >= CURDATE()

同样,此查询仅选择昨天的行 例如,如果是凌晨04:00,则返回昨天00:00 AM到(但不包括)今天00:00 AM之间的所有行:

SELECT * FROM `tbl` WHERE `datetime` >= CURDATE() - INTERVAL 1 DAY AND `datetime` < CURDATE()

我使用上面的语法进行日期查询,我相信它比日期添加/子函数更具可读性。

答案 2 :(得分:0)

为什么不这样做:

SELECT ... WHERE timestamp BETWEEN DATE_SUB(NOW(), INTERVAL 1 DAY) AND NOW()

答案 3 :(得分:0)

您通常会像这样编码:

...
where timestamp > subdate(now(), 1)

请注意subdate()的方便版本,它允许将天指定为简单整数(即默认区间类型为DAY)。此外,如果第一个参数是daretine,则subdate返回日期时间。

答案 4 :(得分:0)

DATEDIFF忽略时间分量(请参阅DATEDIFF - MariaDB Knowledge),而TIMESTAMPDIFF则不忽略。这样就可以了:

SELECT ... WHERE TIMESTAMPDIFF(DAY, NOW(), `timestamp`) = '0'

例如,如果NOW()='2020-01-02 00:00:01'并且timestamp为'2020-01-01 01:00:00',则上述代码将准确返回0天,但DATEDIFF会错误地返回1天(因为它忽略了时间部分。