我有各种活动的记录,其开始和结束时间可能跨越几小时,如12:00 = 13:30。我需要将时间分配到几小时,以便将时间分配为该活动的12:00 - 1小时,13:00,00:00。实现这一目标的最佳方法是什么?
这是创建表,插入和预期结果。需要帮助请叫我。谢谢!
CREATE TABLE Z_SCHED_ACTIVITY
(
SCHED_ACTIVITY_ID decimal(38),
STARTTIME timestamp,
ENDTIME timestamp,
ACTIVITY_ID decimal(38),
EMPLOYEE_ID decimal(38),
SHIFT_ID decimal(38)
);
插入:
INSERT INTO Z_SCHED_ACTIVITY VALUES (16452556,{ts '2013-04-11 01:00:00.0'},{ts '2013-04-11 02:00:00.0'},-4107,5217,252849);
INSERT INTO Z_SCHED_ACTIVITY VALUES (16456677,{ts '2013-04-11 05:30:00.0'},{ts '2013-04-11 05:45:00.0'},-4104,1878,249440);
INSERT INTO Z_SCHED_ACTIVITY VALUES (16457993,{ts '2013-04-11 03:52:00.0'},{ts '2013-04-11 04:07:00.0'},-4104,5217,252849);
INSERT INTO Z_SCHED_ACTIVITY VALUES (16613742,{ts '2013-04-11 08:00:00.0'},{ts '2013-04-11 09:00:00.0'},-4107,1878,249440);
INSERT INTO Z_SCHED_ACTIVITY VALUES (16613744,{ts '2013-04-11 10:30:00.0'},{ts '2013-04-11 10:45:00.0'},-4104,1878,249440);
INSERT INTO Z_SCHED_ACTIVITY VALUES (16613744,{ts '2013-04-10 23:45.00.0'},{ts '2013-04-11 00:45:00.0'},-4104,1878,249440);
EXPECTED RESULT
Shift ID EmployeeID hour start Sched Time Activity
249440 1878 04/10/2013 23:00:00 15 -4104
249440 1878 04/11/2013 00:00:00 45 -4104
249440 1878 04/11/2013 05:00:00 15 -4104
249440 1878 04/11/2013 08:00:00 60 -4107
249440 1878 04/11/2013 10:00:00 15 -4104
252849 5217 04/11/2013 01:00:00 60 -4107
252849 5217 04/11/2013 03:00:00 8 -4104
252849 5217 04/11/2013 04:00:00 7 -4104
答案 0 :(得分:0)
一个有用的技巧是从数据中生成所有可能的每小时时段,然后将其用作连接的一部分,例如:
select min_start + ((level - 1) / 24) as hour_start,
min_start + (level / 24) as hour_end
from (
select trunc(min(starttime), 'HH') as min_start,
trunc(max(endtime), 'HH') as max_end
from z_sched_activity
)
connect by level <= ((max_end - min_start) * 24) + 1;
HOUR_START HOUR_END
------------------- -------------------
04/10/2013 23:00:00 04/11/2013 00:00:00
04/11/2013 00:00:00 04/11/2013 01:00:00
04/11/2013 01:00:00 04/11/2013 02:00:00
04/11/2013 02:00:00 04/11/2013 03:00:00
04/11/2013 03:00:00 04/11/2013 04:00:00
04/11/2013 04:00:00 04/11/2013 05:00:00
04/11/2013 05:00:00 04/11/2013 06:00:00
04/11/2013 06:00:00 04/11/2013 07:00:00
04/11/2013 07:00:00 04/11/2013 08:00:00
04/11/2013 08:00:00 04/11/2013 09:00:00
04/11/2013 09:00:00 04/11/2013 10:00:00
04/11/2013 10:00:00 04/11/2013 11:00:00
12 rows selected.
您可以在匹配期间加入基表:
with hours as (
select min_start + ((level - 1) / 24) as hour_start,
min_start + (level / 24) as hour_end
from (
select trunc(min(starttime), 'HH') as min_start,
trunc(max(endtime), 'HH') as max_end
from z_sched_activity
)
connect by level <= ((max_end - min_start) * 24) + 1
)
select h.hour_start, h.hour_end, zsa.sched_activity_id, zsa.starttime,
zsa.endtime, zsa.activity_id, zsa.employee_id, zsa.shift_id
from hours h
join z_sched_activity zsa
on not (zsa.starttime >= h.hour_end or zsa.endtime < h.hour_start)
order by h.hour_start, zsa.sched_activity_id, zsa.starttime;
我不会显示输出,因为它有点乱,但它会显示所有句点,其中一个或多个句点与基础数据starttime
和endtime
重叠。
然后,您可以计算每个伪记录在匹配期间的时间量:
with hours as (
select min_start + ((level - 1) / 24) as hour_start,
min_start + (level / 24) as hour_end
from (
select trunc(min(starttime), 'HH') as min_start,
trunc(max(endtime), 'HH') as max_end
from z_sched_activity
)
connect by level <= ((max_end - min_start) * 24) + 1
)
select zsa.shift_id, zsa.employee_id, h.hour_start,
(60*24) * (least(h.hour_end, zsa.endtime)
- greatest(h.hour_start, zsa.starttime)) as sched_time,
zsa.activity_id
from hours h
join z_sched_activity zsa
on not (zsa.starttime >= h.hour_end or zsa.endtime < h.hour_start)
order by zsa.shift_id, zsa.employee_id, h.hour_start, zsa.sched_activity_id;
SHIFT_ID EMPLOYEE_ID HOUR_START SCHED_TIME ACTIVITY_ID
---------- ----------- ------------------- ---------- -----------
249440 1878 04/10/2013 23:00:00 15 -4104
249440 1878 04/11/2013 00:00:00 45 -4104
249440 1878 04/11/2013 05:00:00 15 -4104
249440 1878 04/11/2013 08:00:00 60 -4107
249440 1878 04/11/2013 09:00:00 0 -4107
249440 1878 04/11/2013 10:00:00 15 -4104
252849 5217 04/11/2013 01:00:00 60 -4107
252849 5217 04/11/2013 02:00:00 0 -4107
252849 5217 04/11/2013 03:00:00 8 -4104
252849 5217 04/11/2013 04:00:00 7 -4104
10 rows selected.
这里有点奇怪的是,对于endtime
2013-04-11 02:00:00.0
的记录,该结束时间可以说是在下一个小时的开始,这为您提供sched_time
的记录零。您可以通过重复计算将它们排除在where
子句中,或者将其包装在外部select
中,而不是将其删除,或者您可以添加另一个连接条件,以便根本不考虑它们:
...
from hours h
join z_sched_activity zsa
on not (zsa.starttime >= h.hour_end or zsa.endtime < h.hour_start)
and zsa.endtime != h.hour_start
...
SHIFT_ID EMPLOYEE_ID HOUR_START SCHED_TIME ACTIVITY_ID
---------- ----------- ------------------- ---------- -----------
249440 1878 04/10/2013 23:00:00 15 -4104
249440 1878 04/11/2013 00:00:00 45 -4104
249440 1878 04/11/2013 05:00:00 15 -4104
249440 1878 04/11/2013 08:00:00 60 -4107
249440 1878 04/11/2013 10:00:00 15 -4104
252849 5217 04/11/2013 01:00:00 60 -4107
252849 5217 04/11/2013 03:00:00 8 -4104
252849 5217 04/11/2013 04:00:00 7 -4104
8 rows selected.