一定有什麼比這更簡單的方法,但至少你也許可以跟隨每一個步驟分別:
declare @t table ([User] varchar(19) not null,Start datetime2 not null,[End] datetime2 not null)
insert into @t([User], Start, [End]) values
('UserA','2016-01-15T12:00:00','2016-01-15T14:00:00'),
('UserA','2016-01-15T15:00:00','2016-01-15T17:00:00'),
('UserB','2016-01-15T13:00:00','2016-01-15T15:00:00'),
('UserB','2016-01-15T13:32:00','2016-01-15T15:00:00'),
('UserB','2016-01-15T15:30:00','2016-01-15T15:30:00'),
('UserB','2016-01-15T15:45:00','2016-01-15T16:00:00'),
('UserB','2016-01-15T17:30:00','2016-01-15T18:00:00')
;With Times as (
select Start as Point from @t
union
select [End] from @t
), Ordered as (
select Point,ROW_NUMBER() OVER (ORDER BY Point) as rn
from Times
), Periods as (
select
o1.Point as Start,
o2.Point as [End]
from
Ordered o1
inner join
Ordered o2
on
o1.rn = o2.rn - 1
), UserCounts as (
select p.Start,p.[End],COUNT(distinct [User]) as Cnt,ROW_NUMBER() OVER (Order BY p.[Start]) as rn
from
Periods p
left join
@t t
on
p.Start < t.[End] and
t.Start < p.[End]
group by
p.Start,p.[End]
), Consolidated as (
select uc.*
from
UserCounts uc
left join
UserCounts uc_anti
on
uc.rn = uc_anti.rn + 1 and
uc.Cnt = uc_anti.Cnt
where
uc_anti.Cnt is null
union all
select c.Start,uc.[End],c.Cnt,uc.rn
from
Consolidated c
inner join
UserCounts uc
on
c.Cnt = uc.Cnt and
c.[End] = uc.Start
)
select
Start,MAX([End]) as [End],Cnt
from
Consolidated
group by
Start,Cnt
order by Start
CTE s爲 - Times
- 因爲任何給定的開始或結束的郵票可以開始或結束在最後的結果中,我們只是將它們全部放在一列中 - 所以Ordered
可以對它們進行編號,因此Periods
可以將它們重新組裝到每個最小可能的時間段。
UserCounts
然後返回到原始數據,並找出有多少用戶與每個計算週期重疊。
Consolidated
是最棘手的CTE要遵循的,但它基本上是合併期間,彼此相鄰的用戶數相等。
結果:
Start End Cnt
--------------------------- --------------------------- -----------
2016-01-15 12:00:00.0000000 2016-01-15 13:00:00.0000000 1
2016-01-15 13:00:00.0000000 2016-01-15 14:00:00.0000000 2
2016-01-15 14:00:00.0000000 2016-01-15 15:45:00.0000000 1
2016-01-15 15:45:00.0000000 2016-01-15 16:00:00.0000000 2
2016-01-15 16:00:00.0000000 2016-01-15 17:00:00.0000000 1
2016-01-15 17:00:00.0000000 2016-01-15 17:30:00.0000000 0
2016-01-15 17:30:00.0000000 2016-01-15 18:00:00.0000000 1
(我甚至得到了零排我不確定我能想象到的存在)
您真的需要'0'行嗎?基於零源行將行變爲存在可能會非常棘手。 –
你從哪裏獲得期望結果集的開始和結束時間?它們與您的數據不匹配,並且不符合模式。 –
@devlincarnate - 我認爲具有相同用戶數的相鄰時段會被整合,而且用戶似乎有相互重疊的約會。 –