Select 其中 unix 时间戳落在指定的小时或日期
Select where unix timestamp falls on specified hour or day
我正在尝试为 MySQL 查询构建动态位置。用户可以 select 他们想要多少小时或几天前的数据。我希望数据落在特定的几小时或几天前。
这是我现在正在使用但不起作用的代码:
$condition['dates'] = 'Specific';
$condition['date_operand'] = 'Hour(s) ago';
$condition['date_value'] = '3';
if ($conditions['dates'] == 'Specific' && !empty($conditions['date_value'])) {
if ($conditions['date_operand'] == 'Hour(s) ago') {
$where[] = "date_format(from_unixtime(l.date_updated), '%Y-%m-%d %H') = date_format(now() - interval ".$conditions['date_value']." hour, '%Y-%m-%d %H')";
}
else if ($conditions['date_operand'] == 'Day(s) ago') {
$where[] = "date_format(from_unixtime(l.date_updated), '%Y-%m-%d') = date_format(now() - interval ".$conditions['date_value']." day, '%Y-%m-%d')";
}
}
它似乎没有任何作用。 l.date_updated
是一个 unix 时间戳。你可以看到我正在努力实现的目标,它就是行不通。
更新
示例中的 MySQL where 语句不起作用:
SELECT * FROM mytable l
WHERE DATE_FORMAT(FROM_UNIXTIME(l.date_updated), '%Y-%m-%d %H') = DATE_FORMAT(NOW() - INTERVAL 3 HOUR, '%Y-%m-%d %H')
它不会导致错误,只是 select 不是我想要的。
最终更新
我的查询实际上没问题。看来我的 PHP 代码正在连接到多年未更新的开发数据库。这就是我 3 天前 selected 返回零行的原因。
所以,请给我一点尊重,因为我是白痴之王狄翁。
您可以使用 TO_SECONDS:
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_to-seconds
... where TO_SECONDS(l.date_updated) >= TO_SECONDS(NOW()-INTERVAL 3 HOUR)
在我看来,您想选择 date_updated
值位于某个时间范围内的行。例如,我 认为 你的意思是,如果 NOW()
是 2017-04-03 17:55:22
,你希望所有记录的时间戳都在 2017-04-03 14:00:00
和 2017-04-03 14:59:59.99999
之间(含) .
以下是您如何以 sargable 方式执行此操作:一种可以在 date_updated
列上使用索引的方式。
此表达式将 NOW()
截断到小时的开头:17:55 到 17:00:
DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
这会备份三个小时。
DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 3 HOUR
您的时间戳范围的开头是:
UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 3 HOUR)
您的时间戳范围的末尾是
UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 2 HOUR)
所以,这个 WHERE
子句就可以了。
WHERE l.date_updated >= UNIX_TIMESTAMP(DATE_FORMAT(NOW(),'%Y-%m-%d %H:00:00')-INTERVAL 3 HOUR)
AND l.date_updated) < UNIX_TIMESTAMP(DATE_FORMAT(NOW(),'%Y-%m-%d %H:00:00')-INTERVAL 2 HOUR)
请注意时间范围末尾的 <
,而不是 <=
。
这里发生了一些时区问题。 Unix 时间戳(或应该)始终根据 UTC 记录。 UNIX_TIMESTAMP()
函数总是从本地时间转换为 UTC,而 NOW()
函数总是在本地时间工作,所以这一切都应该正常工作。但是如果您仍然得到错误的行或没有行,您可能会调查所有这些时间戳垃圾。
请注意,如果您的列具有 TIMESTAMP
数据类型而不是 INT
数据类型,那么您的时间精度将是相同的,并且您的生活会更轻松。
我正在尝试为 MySQL 查询构建动态位置。用户可以 select 他们想要多少小时或几天前的数据。我希望数据落在特定的几小时或几天前。
这是我现在正在使用但不起作用的代码:
$condition['dates'] = 'Specific';
$condition['date_operand'] = 'Hour(s) ago';
$condition['date_value'] = '3';
if ($conditions['dates'] == 'Specific' && !empty($conditions['date_value'])) {
if ($conditions['date_operand'] == 'Hour(s) ago') {
$where[] = "date_format(from_unixtime(l.date_updated), '%Y-%m-%d %H') = date_format(now() - interval ".$conditions['date_value']." hour, '%Y-%m-%d %H')";
}
else if ($conditions['date_operand'] == 'Day(s) ago') {
$where[] = "date_format(from_unixtime(l.date_updated), '%Y-%m-%d') = date_format(now() - interval ".$conditions['date_value']." day, '%Y-%m-%d')";
}
}
它似乎没有任何作用。 l.date_updated
是一个 unix 时间戳。你可以看到我正在努力实现的目标,它就是行不通。
更新
示例中的 MySQL where 语句不起作用:
SELECT * FROM mytable l
WHERE DATE_FORMAT(FROM_UNIXTIME(l.date_updated), '%Y-%m-%d %H') = DATE_FORMAT(NOW() - INTERVAL 3 HOUR, '%Y-%m-%d %H')
它不会导致错误,只是 select 不是我想要的。
最终更新
我的查询实际上没问题。看来我的 PHP 代码正在连接到多年未更新的开发数据库。这就是我 3 天前 selected 返回零行的原因。
所以,请给我一点尊重,因为我是白痴之王狄翁。
您可以使用 TO_SECONDS: https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_to-seconds
... where TO_SECONDS(l.date_updated) >= TO_SECONDS(NOW()-INTERVAL 3 HOUR)
在我看来,您想选择 date_updated
值位于某个时间范围内的行。例如,我 认为 你的意思是,如果 NOW()
是 2017-04-03 17:55:22
,你希望所有记录的时间戳都在 2017-04-03 14:00:00
和 2017-04-03 14:59:59.99999
之间(含) .
以下是您如何以 sargable 方式执行此操作:一种可以在 date_updated
列上使用索引的方式。
此表达式将 NOW()
截断到小时的开头:17:55 到 17:00:
DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
这会备份三个小时。
DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 3 HOUR
您的时间戳范围的开头是:
UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 3 HOUR)
您的时间戳范围的末尾是
UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 2 HOUR)
所以,这个 WHERE
子句就可以了。
WHERE l.date_updated >= UNIX_TIMESTAMP(DATE_FORMAT(NOW(),'%Y-%m-%d %H:00:00')-INTERVAL 3 HOUR)
AND l.date_updated) < UNIX_TIMESTAMP(DATE_FORMAT(NOW(),'%Y-%m-%d %H:00:00')-INTERVAL 2 HOUR)
请注意时间范围末尾的 <
,而不是 <=
。
这里发生了一些时区问题。 Unix 时间戳(或应该)始终根据 UTC 记录。 UNIX_TIMESTAMP()
函数总是从本地时间转换为 UTC,而 NOW()
函数总是在本地时间工作,所以这一切都应该正常工作。但是如果您仍然得到错误的行或没有行,您可能会调查所有这些时间戳垃圾。
请注意,如果您的列具有 TIMESTAMP
数据类型而不是 INT
数据类型,那么您的时间精度将是相同的,并且您的生活会更轻松。