假设我有以下一个事件表personId,startDate和endDate.
我想知道X人花了多少时间做一个事件(事件可以互相覆盖).
如果这个人只有1个事件,那很容易: datediff(dd, startDate, endDate)
如果这个人有2个事件就很棘手.
我将为预期结果设置一些场景.
场景1
startDate endDate
1 4
3 5
Run Code Online (Sandbox Code Playgroud)
这意味着他的结果应该是1到5的日期
情景2
startDate endDate
1 3
6 9
Run Code Online (Sandbox Code Playgroud)
这意味着他的结果应该是datediff(dd,1,3)和datediff(dd,6,9)
如何在sql查询中获得此结果?我只能想到一堆if语句,但是同一个人可以有n个事件,所以查询会非常混乱.
碎纸机编辑:我想添加第三种情况:
startDate endDate
1 5
4 8
11 15
Run Code Online (Sandbox Code Playgroud)
Shredder场景的理想结果:
(1,5)和(4,8)在(1,8)中合并,因为它们重叠,那么我们需要datediff(1,8) + datediff(11,15)=> 7 + 4 => 11
Mik*_*son 10
您可以使用递归CTE来构建日期列表,然后计算不同的日期.
declare @T table
(
startDate date,
endDate date
);
insert into @T values
('2011-01-01', '2011-01-05'),
('2011-01-04', '2011-01-08'),
('2011-01-11', '2011-01-15');
with C as
(
select startDate,
endDate
from @T
union all
select dateadd(day, 1, startDate),
endDate
from C
where dateadd(day, 1, startDate) < endDate
)
select count(distinct startDate) as DayCount
from C
option (MAXRECURSION 0)
Run Code Online (Sandbox Code Playgroud)
结果:
DayCount
-----------
11
Run Code Online (Sandbox Code Playgroud)
或者您可以使用数字表.这里我使用master..spt_values:
declare @MinStartDate date
select @MinStartDate = min(startDate)
from @T
select count(distinct N.number)
from @T as T
inner join master..spt_values as N
on dateadd(day, N.Number, @MinStartDate) between T.startDate and dateadd(day, -1, T.endDate)
where N.type = 'P'
Run Code Online (Sandbox Code Playgroud)