我有以下数据集
start_time end_time
2017-09-12 12:08:55 2017-09-12 12:10:57
2017-09-12 12:15:10 2017-09-12 12:19:27
2017-09-12 12:24:54 2017-09-12 12:25:35
2017-09-12 12:27:32 2017-09-12 13:20:25
2017-09-12 13:20:25 2017-09-12 13:22:23
2017-09-12 13:32:01 2017-09-12 13:33:57
2017-09-12 13:45:15 2017-09-12 13:46:38
2017-09-12 13:52:52 2017-09-12 13:54:20
2017-09-12 13:59:28 2017-09-12 14:02:32
2017-09-12 14:04:37 2017-09-12 14:07:34
2017-09-12 14:12:49 2017-09-12 14:13:03
2017-09-12 14:34:09 2017-09-12 14:35:47
2017-09-12 14:40:52 2017-09-12 14:46:46
2017-09-12 14:51:57 2017-09-12 14:54:28
我想找到按小时分组的时差之和。由于一些块在一小时内开始但在下一个块中结束,因此计算的总和不是我想要的。举个例子,如果我们采取2017-09-12 12:27:32 - 2017-09-12 13:20:25这个的差异被加到第12个小时并且从第13个小时被忽略。
我正在使用以下查询进行分组和汇总
SELECT
DATE_FORMAT(start_time, "%H") as h,
SEC_TO_TIME(SUM(TIME_TO_SEC(end_time) - TIME_TO_SEC(start_time))) AS timediff
FROM history
WHERE start_time BETWEEN '2017-09-12 12:00:00' and '2017-09-12 15:00:00'
GROUP BY hour(start_time)
获得结果
h timediff
12 00:59:53
13 00:09:49
14 00:13:14
有没有办法打破像2017-09-12 12:27:32 - 2017-09-12 13:20:25这样的区块并将差异分别添加到mysql中的相应小时块?
首选输出
h timediff
12 00:39:28
13 00:27:42
14 00:15:46
(从2017-09-12 12:27:32 - 2017-09-12 13:20:25,32m 28s应该到12小时区块,20m 25s应该到13h区块)
答案 0 :(得分:1)
使用mysql子查询。首先将数据划分为每小时,然后尝试添加时间段。
SELECT SEC_TO_TIME(SUM(t.h)) timediff, t.hc FROM
(
SELECT start_time, end_time,
( UNIX_TIMESTAMP(end_time) - UNIX_TIMESTAMP( start_time ) ) h, HOUR( start_time ) hc from history
WHERE HOUR(end_time) = HOUR(start_time) AND start_time BETWEEN '2017-09-12 12:00:00' and '2017-09-12 15:00:00'
UNION
SELECT start_time, end_time,
( UNIX_TIMESTAMP( end_time ) - UNIX_TIMESTAMP(DATE_FORMAT(end_time, '%Y-%m-%d %H:00:00'))) call_time, HOUR( end_time ) hc from history
WHERE HOUR(end_time) > HOUR(start_time) AND start_time BETWEEN '2017-09-12 12:00:00' and '2017-09-12 15:00:00'
UNION
SELECT start_time, end_time,
( UNIX_TIMESTAMP(DATE_FORMAT(end_time, '%Y-%m-%d %H:00:00')) - UNIX_TIMESTAMP( start_time ) ) call_time, HOUR( start_time ) hc from history
WHERE HOUR(end_time) > HOUR(start_time) AND start_time BETWEEN '2017-09-12 12:00:00' and '2017-09-12 15:00:00'
) t GROUP BY t.hc
答案 1 :(得分:1)
要将时间范围划分为要分组的不同小时数,您可以将其加入到您感兴趣的小时数的临时表中(未经测试):
set @max_duration_mins:=30;
select
start_range,
# overlap between two time ranges is the difference between the greater beginning time and the least ending time (or 0 if that's less than 0)
sum(greatest(
0,
least(
unix_timestamp(date_add(start_range, interval 1 hour)),
unix_timestamp(end_time)
) -
greatest(
unix_timestamp(start_range),
unix_timestamp(start_time)
)
)) total_seconds
from (
select '2017-09-12 12:00:00' start_range
union all select '2017-09-12 13:00:00'
union all select '2017-09-12 14:00:00'
) start_range
cross join history
where start_time between date_sub('2017-09-12 12:00:00', interval @max_duration_mins minute) and '2017-09-12 15:00:00'
group by start_range;
在有无限数量的不同分区的情况下,需要稍微复杂一些的方法,就是将历史记录加入到一个特殊表中,该表可以选择在历史范围内选择多少小时(在您的情况下,这只是0或1)。但除非你感兴趣,否则我不会表明这一点。