-1

我有一张这样的桌子:

create table time_sheet
(
      StatusCode char(1),
      start_time datetime,
      end_time datetime
)

insert into time_sheet values
('W','2012-08-01 10:00:00','2012-08-01 12:00:00'),
('D','2012-08-01 12:00:00','2012-08-01 14:00:00'),
('N','2012-08-01 16:00:00','2012-08-01 18:00:00')

输出应该是这样的:

StatusCode start_time               end_time
B          2012-08-01 08:00:00.000  2012-08-01 10:00:00.000
W          2012-08-01 10:00:00.000  2012-08-01 12:00:00.000
D          2012-08-01 12:00:00.000  2012-08-01 14:00:00.000
B          2012-08-01 14:00:00.000  2012-08-01 16:00:00.000
N          2012-08-01 16:00:00.000  2012-08-01 18:00:00.000
B          2012-08-01 18:00:00.000  2012-08-01 20:00:00.000

一天的开始和结束声明如下。

declare @begingOfDay datetime='2012-08-01 08:00:00.000'
declare @endOfDay    datetime='2012-08-01 20:00:00.000'

基本上,我希望在begingOfDayendOfDay之间的结果集中缺少statusCode B的时间范围记录 。请看输出中有 3 条记录添加了 StatusCode B

有人可以帮忙吗?

4

2 回答 2

1

您的示例数据(注意,T添加到字符串以强制执行明确的日期转换):

create table time_sheet
(
      StatusCode char(1),
      start_time datetime,
      end_time datetime
)

insert into time_sheet values
('W','2012-08-01T10:00:00','2012-08-01T12:00:00'),
('D','2012-08-01T12:00:00','2012-08-01T14:00:00'),
('N','2012-08-01T16:00:00','2012-08-01T18:00:00')

declare @begingOfDay datetime='2012-08-01T08:00:00.000'
declare @endOfDay    datetime='2012-08-01T20:00:00.000'

和查询:

;with AllDTs as (
    select @begingOfDay as TimePoint
    union
    select @endOfDay
    union
    select start_time from time_sheet
    union
    select end_time from time_sheet
), OrderedDTs as (
    select TimePoint,ROW_NUMBER() OVER (ORDER BY TimePoint) as rn
    from AllDTs
), Periods as (
    select o1.TimePoint as start_time,o2.TimePoint as end_time
    from
        OrderedDTs o1
            inner join
        OrderedDTs o2
            on
                o1.rn = o2.rn-1
)
select
    COALESCE(ts.StatusCode,'B') as StatusCode,
    p.start_time,
    p.end_time
from
    Periods p
        left join
    time_sheet ts
        on
            p.start_time = ts.start_time and
            p.end_time = ts.end_time

结果:

StatusCode start_time              end_time
---------- ----------------------- -----------------------
B          2012-08-01 08:00:00.000 2012-08-01 10:00:00.000
W          2012-08-01 10:00:00.000 2012-08-01 12:00:00.000
D          2012-08-01 12:00:00.000 2012-08-01 14:00:00.000
B          2012-08-01 14:00:00.000 2012-08-01 16:00:00.000
N          2012-08-01 16:00:00.000 2012-08-01 18:00:00.000
B          2012-08-01 18:00:00.000 2012-08-01 20:00:00.000

请注意,我假设原始表格中没有重叠的时间段。第一个 CTE ( AllDTs) 只是找到我们感兴趣的所有唯一日期时间值。OrderedDTsPeriods不是将所有这些日期时间值排列成连续的时期。然后,最终查询会获取这些句点中的每一个,并尝试将它们匹配回原始表(如果可能)。如果不是,那么它显然是一个B时期。

于 2012-08-01T12:20:33.473 回答
1

试试这个:

declare @begingOfDay datetime='2012-08-01 08:00:00.000'
declare @endOfDay    datetime='2012-08-01 20:00:00.000'




 declare @begingOfDay datetime='2012-08-01 08:00:00.000'
declare @endOfDay    datetime='2012-08-01 20:00:00.000'


;WITH CTEMain as (select ROW_NUMBER() over (order by (select 0)) as id,StatusCode,start_time,end_time from time_sheet)

,CTE2 as (
select * from (

select    CASE WHEN start_time > @begingOfDay then 'B' else StatusCode end as statusCode,
          CASE WHEN start_time > @begingOfDay then @begingOfDay else start_time end as start_time,
          CASE WHEN start_time > @begingOfDay then start_time else end_time end as end_time
          FROM CTEMain where id=1
UNION
select StatusCode,start_time,end_time from CTEMain 
union 

select 'B'
       ,CASE WHEN CAST(((select c.start_time from CTEMain c where c.id=t1.id+1)-t1.end_time) as time) > '00:00:00' then end_time  else null end as start_time
       ,CASE WHEN CAST(((select c.start_time from CTEMain c where c.id=t1.id+1)-t1.end_time) as time) > '00:00:00' then end_time+((select c.start_time from CTEMain c where c.id=t1.id+1)-t1.end_time)  else null end as start_time
     from CTEMain t1


     ) a)

select * from (  
select * from CTE2 where start_time is not null
union all
select 'B',CASE WHEN MAX(end_time) = @endOfDay then null else  MAX(end_time) end as start_time,@endOfDay as end_time from CTE2) a order by start_time 
于 2012-08-02T07:49:29.013 回答