我有一张这样的表:
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'
基本上我希望在 begingOfDay 和 endOfDay 之间的结果集中缺少时间范围记录,其中statusCode B 。请注意,在输出中有3条记录添加了StatusCode B
有人可以帮忙吗?
答案 0 :(得分: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
)只找到我们感兴趣的所有唯一日期时间值。 OrderedDTs
和Periods
比将所有这些日期时间值安排到连续的时间段中。然后,最终查询将获取每个句点,并尝试将它们与原始表匹配,如果可能的话。如果没有,那么显然是B
期。