如何使用T-SQL将时间排名数据转换为“时间轴”

时间:2011-06-21 11:32:56

标签: sql-server tsql

我有一组数据

        Agent   Rank    START   STOP    CODE
        Joey    52      11:30   11:45   BRK_Break1
        Joey    53      17:30   17:45   BRK_Break2
        Joey    57      14:15   15:15   BRK_Lunch
        Joey    152     09:40   19:00   CONT_Shift

这是整个数据中的人“状态”。逻辑需要是每个“时间段”有一行,所以它根据等级创建一个连续的“时间轴”(更低=更高的优先级),所以它看起来像下面

Agent   Start   Stop    Code
Joey    09:40   11:30   CONT_Shift
Joey    11:30   11:45   BRK_Break1
Joey    11:45   14:15   CONT_Shift
Joey    14:15   15:15   BRK_Lunch
Joey    15:15   17:30   CONT_Shift
Joey    17:30   17:45   BRK_Break2
Joey    17:45   19:00   CONT_Shift

任何想法如何实现这一目标?理想情况下,我想限制使用临时表,并通过CTE或可能是一些自联接但不确定从哪里开始执行此操作?

1 个答案:

答案 0 :(得分:2)

这是一个非常好的问题,回答它很难。首先,我等待其他人解决,但由于没有发生,我试了一下,发现了一个错误并再次尝试。

它不漂亮,但似乎sql中没有支持该问题的功能。所以sql非常复杂。如果其他人提出了一个不同的更好的解决方案,我将是第一个给它加分的人。

declare @t table (name varchar(10), rank int, start datetime, stop datetime, code varchar(12))
insert @t values ('Joey', 52, '2011-06-21 11:30', '2011-06-21 11:45', 'BRK_Break1')     
insert @t values ('Joey', 53, '2011-06-21 17:30', '2011-06-21 17:45', 'BRK_Break2')         
insert @t values ('Joey', 57, '2011-06-21 14:15', '2011-06-21 15:15', 'BRK_Lunch')     
insert @t values ('Joey',152, '2011-06-21 09:40', '2011-06-21 19:00', 'CONT_Shift')
insert @t values ('Joey',152, '2011-06-22 09:40', '2011-06-22 19:00', 'CONT_Shift')

;with aa as
(
select name, rank, start, 'b' action, code from @t
union all
select name, rank, stop,  'e', code from @t
)
select * from (
select name,start, 
(select min(start) from aa where start > a.start and a.name = name) stop, 
(select code from (select rank() OVER (ORDER BY rank) as rank, code from @t where dateadd(second, 1, a.start) between start and stop and name = a.name) c where rank = 1) code
from aa a
where not exists (select 1 from @t where a.start between start and stop and a.rank > rank and a.name = name)
and exists (select 1 from @t where a.start between start and stop and a.name = name)
) d
where code is not null and 
name = 'Joey'
order by start