从特定日期时间开始,按日期时间桶对MYSQL行进行分组

从特定日期时间开始,按日期时间桶对MYSQL行进行分组,mysql,sql,group-by,Mysql,Sql,Group By,假设我有几列,其中一列的日期时间如下: 2015-07-19 17:00:01 2015-07-19 17:15:01 2015-07-19 17:30:01 2015-07-19 17:45:01 2015-07-19 18:00:01 2015-07-19 18:15:01 2015-07-19 18:30:01 2015-07-19 18:45:01 2015-07-19 19:00:01 2015-07-19 19:15:01 2015-07-19 19:30:01 2015-07-19

假设我有几列,其中一列的日期时间如下:

2015-07-19 17:00:01
2015-07-19 17:15:01
2015-07-19 17:30:01
2015-07-19 17:45:01
2015-07-19 18:00:01
2015-07-19 18:15:01
2015-07-19 18:30:01
2015-07-19 18:45:01
2015-07-19 19:00:01
2015-07-19 19:15:01
2015-07-19 19:30:01
2015-07-19 19:45:01
2015-07-19 20:00:01
2015-07-19 20:15:01
出于聚合目的,我希望输出每3小时循环一次:

2015-07-19 17:00:01, max(column B), etc
2015-07-19 20:00:01, max(column B), etc
2015-07-19 23:00:01, max(column B), etc
2015-07-20 02:00:01, max(column B), etc
我的尝试:

SELECT
datetime_col,
min(col_b)
FROM table
where datetime_col >= STR_TO_DATE('2015-07-19 17:00:01','%Y-%m-%d %H:%i:%s')
GROUP BY
YEAR(datetime_col),
MONTH(datetime_col),
DAY(datetime_col),
ROUND(HOUR(datetime_col)/3);
实际产量:

2015-07-19 17:00:01
2015-07-19 20:00:01
2015-07-19 23:00:01
2015-07-20 00:00:01
2015-07-20 02:00:01
您可以看到,在开始新的一天之前,分组看起来很好。我需要将其分组为3小时周期,而不考虑日、月、年等


最好是在单个查询中完成,因为我在C#应用程序中调用它

简单的方法是创建一个包含日期和小时范围的表

这是一个关于day的例子,你需要用小时来扩展

因此,您将拥有
hour\u块
表格

id   startTime            endTime
 1   2015-07-19 00:00:01  2015-07-19 03:00:00
 2   2015-07-19 03:00:01  2015-07-19 06:00:00
 3   2015-07-19 06:00:01  2015-07-19 09:00:00
 ...         ...                ...
 8   2015-07-19 21:00:01  2015-07-20 00:00:00
然后创建一个连接

 SELECT H.id, H.startTime, max(Y.column B)
 From YourTable Y
 JOIN hour_block H
   ON Y.datetime_col between H.startTime and H.endTime
 GROUP BY H.id, H.startTime

简单的方法是创建一个包含日期和小时范围的表

这是一个关于day的例子,你需要用小时来扩展

因此,您将拥有
hour\u块
表格

id   startTime            endTime
 1   2015-07-19 00:00:01  2015-07-19 03:00:00
 2   2015-07-19 03:00:01  2015-07-19 06:00:00
 3   2015-07-19 06:00:01  2015-07-19 09:00:00
 ...         ...                ...
 8   2015-07-19 21:00:01  2015-07-20 00:00:00
然后创建一个连接

 SELECT H.id, H.startTime, max(Y.column B)
 From YourTable Y
 JOIN hour_block H
   ON Y.datetime_col between H.startTime and H.endTime
 GROUP BY H.id, H.startTime

我将通过将值转换为最接近的前3小时周期来处理此问题。使用
到_seconds()。因此:

SELECT FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(datetimecol) / (60 * 60 / 3) )) as datetime,
      min(col_b)
FROM table
WHERE datetime_col >= STR_TO_DATE('2015-07-19 17:00:01', '%Y-%m-%d %H:%i:%s')
GROUP BY FLOOR(UNIX_TIMESTAMP(datetimecol) / (60 * 60 / 3) )

我将通过将值转换为最接近的前3小时周期来处理此问题。使用
到_seconds()。因此:

SELECT FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(datetimecol) / (60 * 60 / 3) )) as datetime,
      min(col_b)
FROM table
WHERE datetime_col >= STR_TO_DATE('2015-07-19 17:00:01', '%Y-%m-%d %H:%i:%s')
GROUP BY FLOOR(UNIX_TIMESTAMP(datetimecol) / (60 * 60 / 3) )

假设你有3个小时的间隔

CREATE TABLE T
(dcol datetime,b INT);

INSERT INTO t
VALUES('2015-07-19 17:00:01',23),
('2015-07-19 18:30:01',25),
('2015-07-19 19:00:01',66),
('2015-07-19 20:00:01',99),
('2015-07-19 21:00:01',5),
('2015-07-19 23:00:01',2),
('2015-07-20 02:00:01',78),
('2015-07-20 03:00:01',9),
('2015-07-20 05:00:01',11),
('2015-07-20 07:00:01',29)

SELECT t.dcol,t.b
FROM t JOIN t tt WHERE t.dcol=tt.dcol+INTERVAL 3 HOUR
UNION
SELECT tt.dcol,tt.b
FROM t JOIN t tt WHERE t.dcol=tt.dcol+INTERVAL 3 HOUR
ORDER BY dcol

dcol                 b
2015-07-19 17:00:01  23
2015-07-19 20:00:01  99
2015-07-19 23:00:01  2
2015-07-20 02:00:01  78
2015-07-20 05:00:01  11

假设你有3个小时的间隔

CREATE TABLE T
(dcol datetime,b INT);

INSERT INTO t
VALUES('2015-07-19 17:00:01',23),
('2015-07-19 18:30:01',25),
('2015-07-19 19:00:01',66),
('2015-07-19 20:00:01',99),
('2015-07-19 21:00:01',5),
('2015-07-19 23:00:01',2),
('2015-07-20 02:00:01',78),
('2015-07-20 03:00:01',9),
('2015-07-20 05:00:01',11),
('2015-07-20 07:00:01',29)

SELECT t.dcol,t.b
FROM t JOIN t tt WHERE t.dcol=tt.dcol+INTERVAL 3 HOUR
UNION
SELECT tt.dcol,tt.b
FROM t JOIN t tt WHERE t.dcol=tt.dcol+INTERVAL 3 HOUR
ORDER BY dcol

dcol                 b
2015-07-19 17:00:01  23
2015-07-19 20:00:01  99
2015-07-19 23:00:01  2
2015-07-20 02:00:01  78
2015-07-20 05:00:01  11

按楼层分组(unix\u时间戳(datetime\u col)/(3*3600))怎么样?
按楼层分组(unix\u时间戳(datetime\u col)/(3*3600)怎么样
?范围条件下的联接不能使用索引。@Vatev你能分享一些文档来描述这一事实吗?事实不需要文档:)在这种情况下,它实际上比范围条件问题更糟糕,因为联接使用两个不同的列,即使可以在一个范围上联接,也只会使用其中一个列(在这种情况下,它与没有索引一样糟糕)@ VATEV是的,他们需要一个,如果你不提供一个证明只是一个假设。把它当作一个警告。任何决定使用它的人都应该检查查询计划并考虑性能的影响。我的目标不是证明你错了或者任何这样的事情。连接范围条件不能使用索引。@ VATEV你能分享一些文档吗?描述这个事实?事实不需要文档:)在这种情况下,它实际上比范围条件问题更糟糕,因为连接使用两个不同的列,即使可以在一个范围上连接,也只会连接其中一个(在这种情况下,这与没有索引一样糟糕)。@Vatev是的,他们需要一个,如果你不提供证据,那只是一个假设。把它当作一个警告。决定使用此选项的任何人都应该检查查询计划并考虑性能影响。我的目标不是要证明你错了或诸如此类的事情,这是行不通的。我需要分组,这样我可以在3小时内对值进行一些聚合。这将不起作用。我需要分组,以便在3小时内对值进行聚合