【发布时间】:2012-03-29 14:59:02
【问题描述】:
我在 MySQL 数据库中有一个日期时间字段,并希望将结果输出到最接近的时间。
例如2012-04-01 00:00:01 应改为 2012-04-01 00:00:00
【问题讨论】:
我在 MySQL 数据库中有一个日期时间字段,并希望将结果输出到最接近的时间。
例如2012-04-01 00:00:01 应改为 2012-04-01 00:00:00
【问题讨论】:
更新:我认为https://stackoverflow.com/a/21330407/480943 是一个更好的答案。
你可以用一些日期算术来做到这一点:
SELECT some_columns,
DATE_ADD(
DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00"),
INTERVAL IF(MINUTE(the_date) < 30, 0, 1) HOUR
) AS the_rounded_date
FROM your_table
解释:
DATE_FORMAT:DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00") 返回截断到最接近小时的日期(将分钟和秒部分设置为零)。
MINUTE:MINUTE(the_date)获取日期的分钟值。
IF:这是有条件的;如果参数1中的值为真,则返回参数2,否则返回参数3。所以IF(MINUTE(the_date) < 30, 0, 1)的意思是“如果分钟值小于30,则返回0,否则返回1”。这就是我们要用来四舍五入的——它是要重新添加的小时数。
DATE_ADD:这会将回合的小时数添加到结果中。
【讨论】:
半小时是 30 分钟。只需将 30 分钟添加到时间戳并截断分钟和秒。
SELECT DATE_FORMAT(DATE_ADD(timestamp_column, INTERVAL 30 MINUTE),'%Y-%m-%d %H:00:00') FROM table
【讨论】:
soul 的第一个解决方案是截断而不是舍入,第二个解决方案不适用于夏令时情况,例如:
select FROM_UNIXTIME(UNIX_TIMESTAMP('2012-03-11 2:14:00') - MOD(UNIX_TIMESTAMP('2012-03-11 2:14:00'),300));
这是另一种方法(1):
DATE_ADD(
tick,
INTERVAL (IF((MINUTE(tick)*60)+SECOND(tick) < 1800, 0, 3600) - (MINUTE(tick)*60)+SECOND(tick)) SECOND
)
如果你不需要担心秒,你可以像这样简化它(2):
DATE_ADD(
tick,
INTERVAL (IF(MINUTE(tick) < 30, 0, 60) - MINUTE(tick)) MINUTE
)
或者如果你喜欢截断而不是舍入,这里是灵魂方法(3)的更简单版本:
DATE_SUB(tick, INTERVAL MINUTE(tick)*60+SECOND(tick) SECOND)
编辑:我在本地机器上分析了其中一些查询,发现 100,000 行的平均时间如下:
UNIXTIME 方法:0.0423 毫秒(快,但不适用于 DST)DATE_FORMAT 方法:0.1495 毫秒【讨论】:
DATE_FORMAT 很慢?我从来没有听说过。您对此有参考/基准吗?我在谷歌上找不到任何关于 DATE_FORMAT 性能不佳的信息,也没有任何迹象表明对 MINUTE() 和 SECOND() 的调用会比对 DATE_FORMAT 的调用快得多。在任何情况下,任何性能差异不应该是纳秒级的——对于几乎所有现实世界的目的来说基本上是不可见/可以忽略不计的?
MINUTE/SECOND 慢得多,但在分析了这两种情况之后,情况并非如此。你的解决方案甚至可能比我的要快一点(可能是因为我两次调用MINUTE 和SECOND?)。但是,我省略秒的示例比DATE_FORMAT 快。我会更新我的答案。
timestamp,date_sub(timestamp,interval (minute(timestamp) % 15)* 60 +second(timestamp) second)...
来自How to round a DateTime in MySQL?:
当您使用日期时间数据类型时,这有点令人讨厌;存储函数的理想候选者。
DATE_SUB(DATE_SUB(time, INTERVAL MOD(MINUTE(time),5) MINUTE ), INTERVAL SECOND(time) SECOND)使用 UNIXTIME 时间戳会更容易,但仅限于 1970 - 2038 日期范围。
FROM_UNIXTIME(UNIX_TIMESTAMP(time) - MOD(UNIX_TIMESTAMP(time),300))祝你好运。
【讨论】:
select FROM_UNIXTIME(UNIX_TIMESTAMP('2012-03-11 2:14:00') - MOD(UNIX_TIMESTAMP('2012-03-11 2:14:00'),300));
【讨论】:
这将返回下一个小时,即'2012-01-02 18:02:30'将转换为'2012-01-02 19:00:00'
TIMESTAMPADD(HOUR,
TIMESTAMPDIFF(HOUR,CURDATE(),timestamp_column_name),
CURDATE())
您可以使用任意日期来代替CURDATE(),例如'2000-01-01'
如果系统日期在两次调用函数之间发生变化,不确定使用CURDATE()是否会出现问题,不知道Mysql是否会同时调用这两个函数。
获得最近的小时是:
TIMESTAMPADD(MINUTE,
ROUND(TIMESTAMPDIFF(MINUTE,CURDATE(),timestamp_column_name)/60)*60,
CURDATE())
将 60 更改为 15 将获得最近的 15 分钟间隔,使用 SECOND 可以获得最接近的所需秒间隔,等等。
要获取前一小时的信息,请使用 TRUNCATE() 或 FLOOR() 而不是 ROUND()。
希望这会有所帮助。
【讨论】:
如果您需要将时间四舍五入到下一个小时,您可以使用这个:
SELECT TIME_FORMAT(
ADDTIME(
TIMEDIFF('16:15', '10:00'), '00:59:00'
),
'%H:00:00'
)
【讨论】:
我认为这是最好的方法,因为它也将使用最少的资源-
date_add(date(date_completed), interval hour(date_completed) hour) as date_hr
【讨论】: