MySQL - 按十五分钟间隔对时间范围进行分组
MySQL - Grouping Time Ranges by Fifteen Minute Intervals
所以,我有一个计时系统 table,它跟踪我的员工花费多少时间登录到不同的状态。看起来是这样的:
Employee_ID Queue StartTime End Time
121509 'Break' 2018-05-17 13:31:54 2018-05-17 13:47:02
121509 'Working' 2018-05-17 13:47:04 2018-05-17 15:05:45
121509 'Unavail.' 2018-05-17 15:05:46 2018-05-17 15:32:01
等等。我的目标是汇总所有员工在每个队列状态中花费的时间(通过从 EndTime 中减去 StartTime 得到)并按十五分钟的间隔对该汇总进行分组。我是做的是这样的:
concat(
time_format(convert_tz(StartTime,'UTC','America/Denver'),'%H'),
':',
case
when minute(convert_tz(StartTime,'UTC','America/Denver')) < 15
then '00'
when minute(convert_tz(StartTime,'UTC','America/Denver')) < 30
then '15'
when minute(convert_tz(StartTime,'UTC','America/Denver')) < 45
then '30'
else '45'
end,
':00'
) as 'Interval',
但是,通过以这种方式分组,我意识到如果我以这种方式分组,那么在队列中花费的任何时间都将仅计入员工记录的 第一个 间隔成,而不是将时间分成 StartTime 和 Endtime 之间的时间范围所包含的所有时间间隔。
所以,我的问题是:如何对我的数据进行分组,以便如果给定的时间范围超过它开始时的十五分钟间隔,它就会开始计算 下一个十五分钟的间隔?
示例输出:
Employee_ID Interval Queue QueueTime
121509 13:30 'Break' 00:14:54
121509 13:45 'Break' 00:02:02
121509 13:45 'Working' 00:13:58
121509 14:00 'Working' 00:15:00
121509 14:15 'Working' 00:15:00
121509 14:30 'Working' 00:02:58
121509 14:30 'Unavail.' 00:08:13
121509 14:30 'Break' 00:03:28
我猜您会想要获取时间戳差异,然后按员工和队列类型分组。像这样的查询应该适合您:
SELECT
Employee_ID,
Queue,
SUM(TIMESTAMPDIFF(MINUTE,
StartTime,
EndTime)) AS Time
FROM
EmployeeTable
GROUP BY Employee_ID , Queue;
好的。这花了一些时间,但我在 RToyo 的帮助下弄明白了:
首先:创建一个包含十五分钟间隔的列表:
select
addtime(time('00:00:00'),sec_to_time(900 * (a.a + b.a * 10))) as 'IntervalStart',
addtime(time('00:14:59'),sec_to_time(900 * (a.a + b.a * 10))) as 'IntervalEnd'
from (
select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
where
addtime(time('00:00:00'),sec_to_time(900 * (a.a + b.a * 10))) between '06:00:00' and '18:45:00'
接下来:通过测试 StartTime 和 Endtime 字段之间的重叠来加入计时 table:
left join ( select
addtime(time('00:00:00'),sec_to_time(900 * (a.a + b.a * 10))) as 'Interval Start',
addtime(time('00:14:59'),sec_to_time(900 * (a.a + b.a * 10))) as 'Interval End'
from (
select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
where
addtime(time('00:00:00'),sec_to_time(900 * (a.a + b.a * 10))) between '06:00:00' and '18:45:00') as Intervals
on timekeepingtable.StartTime <= Intervals.IntervalStart
and timekeepingtable.EndTime >= Intervals.IntervalEnd
然后只需将 StartTime 和 EndTime 字段修改为以间隔为界:
if(time(pgrp.StartTime) < Intervals.IntervalStart,Intervals.IntervalStart,time(pgrp.StartTime)) as 'Start Time',
if(time(pgrp.EndTime) > Intervals.IntervalEnd, Intervals.IntervalEnd,time(pgrp.EndTime)) as 'End Time',
所以,我有一个计时系统 table,它跟踪我的员工花费多少时间登录到不同的状态。看起来是这样的:
Employee_ID Queue StartTime End Time
121509 'Break' 2018-05-17 13:31:54 2018-05-17 13:47:02
121509 'Working' 2018-05-17 13:47:04 2018-05-17 15:05:45
121509 'Unavail.' 2018-05-17 15:05:46 2018-05-17 15:32:01
等等。我的目标是汇总所有员工在每个队列状态中花费的时间(通过从 EndTime 中减去 StartTime 得到)并按十五分钟的间隔对该汇总进行分组。我是做的是这样的:
concat(
time_format(convert_tz(StartTime,'UTC','America/Denver'),'%H'),
':',
case
when minute(convert_tz(StartTime,'UTC','America/Denver')) < 15
then '00'
when minute(convert_tz(StartTime,'UTC','America/Denver')) < 30
then '15'
when minute(convert_tz(StartTime,'UTC','America/Denver')) < 45
then '30'
else '45'
end,
':00'
) as 'Interval',
但是,通过以这种方式分组,我意识到如果我以这种方式分组,那么在队列中花费的任何时间都将仅计入员工记录的 第一个 间隔成,而不是将时间分成 StartTime 和 Endtime 之间的时间范围所包含的所有时间间隔。
所以,我的问题是:如何对我的数据进行分组,以便如果给定的时间范围超过它开始时的十五分钟间隔,它就会开始计算 下一个十五分钟的间隔?
示例输出:
Employee_ID Interval Queue QueueTime
121509 13:30 'Break' 00:14:54
121509 13:45 'Break' 00:02:02
121509 13:45 'Working' 00:13:58
121509 14:00 'Working' 00:15:00
121509 14:15 'Working' 00:15:00
121509 14:30 'Working' 00:02:58
121509 14:30 'Unavail.' 00:08:13
121509 14:30 'Break' 00:03:28
我猜您会想要获取时间戳差异,然后按员工和队列类型分组。像这样的查询应该适合您:
SELECT
Employee_ID,
Queue,
SUM(TIMESTAMPDIFF(MINUTE,
StartTime,
EndTime)) AS Time
FROM
EmployeeTable
GROUP BY Employee_ID , Queue;
好的。这花了一些时间,但我在 RToyo 的帮助下弄明白了:
首先:创建一个包含十五分钟间隔的列表:
select
addtime(time('00:00:00'),sec_to_time(900 * (a.a + b.a * 10))) as 'IntervalStart',
addtime(time('00:14:59'),sec_to_time(900 * (a.a + b.a * 10))) as 'IntervalEnd'
from (
select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
where
addtime(time('00:00:00'),sec_to_time(900 * (a.a + b.a * 10))) between '06:00:00' and '18:45:00'
接下来:通过测试 StartTime 和 Endtime 字段之间的重叠来加入计时 table:
left join ( select
addtime(time('00:00:00'),sec_to_time(900 * (a.a + b.a * 10))) as 'Interval Start',
addtime(time('00:14:59'),sec_to_time(900 * (a.a + b.a * 10))) as 'Interval End'
from (
select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
where
addtime(time('00:00:00'),sec_to_time(900 * (a.a + b.a * 10))) between '06:00:00' and '18:45:00') as Intervals
on timekeepingtable.StartTime <= Intervals.IntervalStart
and timekeepingtable.EndTime >= Intervals.IntervalEnd
然后只需将 StartTime 和 EndTime 字段修改为以间隔为界:
if(time(pgrp.StartTime) < Intervals.IntervalStart,Intervals.IntervalStart,time(pgrp.StartTime)) as 'Start Time',
if(time(pgrp.EndTime) > Intervals.IntervalEnd, Intervals.IntervalEnd,time(pgrp.EndTime)) as 'End Time',