2012-05-30 35 views
4

看看这里(linkSQL:拆分事件为多行

我SQLFiddle在SQL Server 2008中,我有事件表开始和结束时间,像下面的图片。

enter image description here

我需要编写一个查询,让我找出多少每个事件的睡着了,工作班次。我们的班次是12小时,从06:00-18:00和18:00-06:00。

该查询应产生如下图所示的结果。

enter image description here

从这一点,然后我就可以计算出总工期事件为特定的工作班次。

我能做些什么来从第一张图片转到第二张图片?

回答

5
With Shifts As 
    (
    Select 1 As Num 
     , Cast('2012-05-01 6:00 AM' As datetime) As ShiftStart 
     , DateAdd(hh,12,Cast('2012-05-01 6:00 AM' As datetime)) As ShiftEnd 
    Union All 
    Select Num + 1, ShiftEnd, DateAdd(hh,12,ShiftEnd) 
    From Shifts 
    Where ShiftEnd < '2012-05-30' 
    ) 
    , Segments As 
    (
    Select event_id 
     , Case 
     When Shifts.ShiftStart > event_start Then Shifts.ShiftStart 
     Else event_start 
     End As start_split_segment   
     , Case 
     When Shifts.ShiftEnd < event_end Then Shifts.ShiftEnd 
     Else event_end 
     End As end_split_segment   
     , Count(*) Over (Partition By E.event_id) As SegmentCount 
    From events As E 
     Join Shifts 
     On E.event_start <= ShiftEnd 
      And E.event_end > ShiftStart 
    ) 
Select E.event_id, E.description, E.event_start, E.event_end 
    , S.start_split_segment, S.end_split_segment 
    , Case When SegmentCount > 1 Then 1 Else 0 End As is_split 
    , NullIf(SegmentCount,1) As split_segments 
From Segments As S 
    Join events As E 
    On E.event_id = S.event_id 

SQL Fiddle version

在这个解决方案,我生成每个班次的开始和结束日期的日历。您可以通过将Where ShiftEnd < '2012-05-30'更改为更大的日期来延长日历。请注意,如果您最终的转换次数超过50次,则您需要在查询结束时添加Option(Maxrecursion 0);以提升SQL Server的上限。

+0

干得好!我无法相信你设法做到了多么简洁。这会为我节省很多麻烦。非常感谢。 –