热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

无论时区如何,都将MySQL日期时间分组为间隔-GroupingMySQLdatetimeintointervalsirrespectiveoftimezone

ThisquestionhasbeenaskedbeforebutIamfacingaslightlydifferentproblem.之前已经问过这个问题,但我面临的问题

This question has been asked before but I am facing a slightly different problem.

之前已经问过这个问题,但我面临的问题略有不同。

I have a table which logs events and stores their timestamps (as datetime). I need to be able to break up time into chunks and get number of events that occurred in that interval. The interval can be custom (Say from 5 minutes to 1 hour and even beyond).

我有一个表记录事件并存储他们的时间戳(作为日期时间)。我需要能够将时间分成块并获得在该间隔中发生的事件的数量。间隔可以是自定义的(比如5分钟到1小时甚至更长)。

The obvious solution is to convert the datetime to unix_timestamp divide it by number of seconds in the interval, take its floor function and multiply it back by the number of seconds. Finally convert the unix_timestamp back to the datetime format.

显而易见的解决方案是将datetime转换为unix_timestamp,将其除以间隔中的秒数,取其底层函数并将其乘以秒数。最后将unix_timestamp转换回日期时间格式。

This works fine for small intervals.

这适用于小间隔。

select 
from_unixtime(floor(unix_timestamp(event.timestamp)/300)*300) as start_time,
count(*) as total 
from event 
where timestamp>='2012-08-03 00:00:00' 
group by start_time;

This gives the correct output

这给出了正确的输出

+---------------------+-------+
| start_time          | total |
+---------------------+-------+
| 2012-08-03 00:00:00 |    11 |
| 2012-08-03 00:05:00 |     4 |
| 2012-08-03 00:10:00 |     4 |
| 2012-08-03 00:15:00 |     7 |
| 2012-08-03 00:20:00 |     8 |
| 2012-08-03 00:25:00 |     1 |
| 2012-08-03 00:30:00 |     1 |
| 2012-08-03 00:35:00 |     3 |
| 2012-08-03 00:40:00 |     3 |
| 2012-08-03 00:45:00 |     5 |
~~~~~OUTPUT SNIPPED~~~~~~~~~~~~

But if I increase the interval to say 1 hour (3600 sec)

但如果我把间隔增加到1小时(3600秒)

mysql> select from_unixtime(floor(unix_timestamp(event.timestamp)/3600)*3600) as start_time, count(*) as total from event where timestamp>='2012-08-03 00:00:00' group by start_time;
+---------------------+-------+
| start_time          | total |
+---------------------+-------+
| 2012-08-02 23:30:00 |    35 |
| 2012-08-03 00:30:00 |    30 |
| 2012-08-03 01:30:00 |    12 |
| 2012-08-03 02:30:00 |    18 |
| 2012-08-03 03:30:00 |    12 |
| 2012-08-03 04:30:00 |     4 |
| 2012-08-03 05:30:00 |     3 |
| 2012-08-03 06:30:00 |    13 |
| 2012-08-03 07:30:00 |   269 |
| 2012-08-03 08:30:00 |   681 |
| 2012-08-03 09:30:00 |  1523 |
| 2012-08-03 10:30:00 |   911 |
+---------------------+-------+

The reason, as far as I could gauge, for the boundaries not being set properly is that unix_timestamp will convert time from my local timezone (GMT + 0530) to UTC and then output the numerical value.

据我所知,未正确设置边界的原因是unix_timestamp会将时间从我的本地时区(GMT + 0530)转换为UTC,然后输出数值。

So a value like 2012-08-03 00:00:00 will actually be 2012-08-02 18:30:00. Dividing and using floor will set the minutes part to 00. But when I use from_unixtime, it will convert it back to GMT + 0530 and hence give me intervals that begin at 30 mins.

所以像2012-08-03 00:00:00这样的值实际上是2012-08-02 18:30:00。划分和使用楼层会将分钟部分设置为00.但是当我使用from_unixtime时,它会将其转换回GMT + 0530,因此给我的间隔时间为30分钟。

How do I ensure the query works correctly irrespective of the timezone? I use MySQL 5.1.52 so to_seconds() is not available

无论时区如何,我如何确保查询正常工作?我使用MySQL 5.1.52所以to_seconds()不可用

EDIT: The query should also fire correctly irrespective of the interval (can be hours, minutes, days). A generic solution would be appreciated

编辑:无论间隔(可以是小时,分钟,天),查询也应该正确触发。一般的解决方案将不胜感激

2 个解决方案

#1


7  

You can use TIMESTAMPDIFF to group by intervals of time:

您可以使用TIMESTAMPDIFF按时间间隔分组:

For a specified interval of hours, you can use:

对于指定的小时间隔,您可以使用:

SELECT   '2012-08-03 00:00:00' + 
         INTERVAL FLOOR(TIMESTAMPDIFF(HOUR, '2012-08-03 00:00:00', timestamp) / ) *  HOUR AS start_time,
         COUNT(*) AS total 
FROM     event 
WHERE    timestamp >= '2012-08-03 00:00:00'
GROUP BY start_time

Replace the occurances of 2012-08-03 00:00:00 with your minimum input date.

用最小输入日期替换2012-08-03 00:00:00的出现。

is your specified interval in hours (every 2 hours, 3 hours, etc.), and you can do the same for minutes:

是您指定的小时间隔(每2小时,3小时等),您可以在几分钟内执行相同操作:

SELECT   '2012-08-03 00:00:00' + 
         INTERVAL FLOOR(TIMESTAMPDIFF(MINUTE, '2012-08-03 00:00:00', timestamp) / ) *  MINUTE AS start_time,
         COUNT(*) AS total 
FROM     event 
WHERE    timestamp >= '2012-08-03 00:00:00'
GROUP BY start_time

Where is your specified interval in minutes (every 45 minutes, 90 minutes, etc).

其中 是您指定的间隔(以分钟为单位)(每45分钟,90分钟等)。

Be sure you're passing in your minimum input date (in this example 2012-08-03 00:00:00) as the second parameter to TIMESTAMPDIFF.

确保您将最小输入日期(在此示例中为2012-08-03 00:00:00)作为TIMESTAMPDIFF的第二个参数传递。


EDIT: If you don't want to worry about which interval unit to pick in the TIMESTAMPDIFF function, then of course just do the interval by seconds (300 = 5 minutes, 3600 = 1 hour, 7200 = 2 hours, etc.)

编辑:如果您不想担心在TIMESTAMPDIFF函数中选择哪个间隔单位,那么当然只需要按秒进行间隔(300 = 5分钟,3600 = 1小时,7200 = 2小时等)

SELECT   '2012-08-03 00:00:00' + 
         INTERVAL FLOOR(TIMESTAMPDIFF(SECOND, '2012-08-03 00:00:00', timestamp) / ) *  SECOND AS start_time,
         COUNT(*) AS total 
FROM     event 
WHERE    timestamp >= '2012-08-03 00:00:00'
GROUP BY start_time

EDIT2: To address your comment pertaining to reducing the number of areas in the statement where you have to pass in your minimum parameter date, you can use:

编辑2:要解决有关减少语句中您必须通过最小参数日期的区域数量的注释,您可以使用:

SELECT   b.mindate + 
         INTERVAL FLOOR(TIMESTAMPDIFF(SECOND, b.mindate, timestamp) / ) *  SECOND AS start_time,
         COUNT(*) AS total 
FROM     event 
JOIN     (SELECT '2012-08-03 00:00:00' AS mindate) b ON timestamp >= b.mindate
GROUP BY start_time

And simply pass in your minimum datetime parameter once into the join subselect.

只需将最小日期时间参数传递到join子选择中即可。

You can even make a second column in the join subselect for your seconds interval (e.g. 3600) and name the column something like secinterval... then change the 's to b.secinterval, so you only have to pass in your minimum date parameter AND interval one time each.

您甚至可以在连接子选择中为秒间隔(例如3600)创建第二列,并将列命名为secinterval ...然后将 更改为b.secinterval,因此您只需要传入最小日期参数和间隔各一次。


SQLFiddle Demo

#2


1  

the easier method would be:

更简单的方法是:

Method1

select date(timestamp) as date_timestamp, hour(timestamp) as hour_timestamp, count(*) as total 
from event
where timestamp>='2012-08-03 00:00:00' 
group by date_timestamp, hour_timestamp

if you would like to use your original approach.

如果你想使用你原来的方法。

Method2

select from_unixtime(floor(unix_timestamp(event.timestamp-1800)/3600)*3600+1800) as start_time, 
count(*) as total 
from event 
where timestamp>='2012-08-03 00:00:00' 
group by start_time;
EDIT1

for the first method, it also allows user to set different interval. For example, if user wants the log to group by 15 minutes,

对于第一种方法,它还允许用户设置不同的间隔。例如,如果用户希望日志分组15分钟,

select date(time) as date_timestamp, 
    hour(time) as hour_timestamp,  
    floor(minute(time) as minute_timestamp / 15) * 15 as minute_timestamp
    count(*) as total
from event
group by date_timestamp, hour_timestamp, minute_timestamp

推荐阅读
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
author-avatar
nancy_liu_tj
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有