**编辑:我们当前的服务器是SQL 2008 R2,所以LAG / LEAD功能不起作用。
我尝试在表中获取多个数据流并将它们合并为一个数据流。鉴于下面的3个数据流,我希望最终结果是1个流,它优先考虑状态' on'。递归似乎是最好的选择,但到目前为止,我还没有运气,把我想做的事情放在一起。
CREATE TABLE #Dates(
id INT IDENTITY,
status VARCHAR(4),
StartDate Datetime,
EndDate Datetime,
booth int)
INSERT #Dates
VALUES
( 'off','2015-01-01 08:00','2015-01-01 08:15',1),
( 'on','2015-01-01 08:15','2015-01-01 09:15',1),
( 'off','2015-01-01 08:50','2015-01-01 09:00',2),
( 'on','2015-01-01 09:00','2015-01-01 09:30',2),
( 'off','2015-01-01 09:30','2015-01-01 09:35',2),
( 'on','2015-01-01 09:35','2015-01-01 10:15',2),
( 'off','2015-01-01 09:30','2015-01-01 10:30',3),
( 'on','2015-01-01 10:30','2015-01-01 11:00',3)
status StartDate EndDate
---------------------------
off 08:00 08:15
on 08:15 09:15
off 08:50 09:00
on 09:00 09:30
off 09:30 09:35
on 09:35 10:15
off 09:30 10:30
on 10:30 11:00
结束结果:
status StartDate EndDate
---------------------------
off 8:00 8:15
on 8:15 9:15
on 9:15 9:30
off 9:30 9:35
on 9:35 10:15
off 10:15 10:30
on 10:30 11:00
基本上,任何时候都有' on'它应该覆盖任何并发的' off'状态。
Source:
|----off----||---------on---------|
|---off--||------on----||---off---||--------on------|
|--------------off------------------||------on------|
Result (Either result would work):
|----off----||----------on--------||---on---||---off---||--------on------||-off--||------on------|
|----off----||----------on------------------||---off---||--------on------||-off--||------on------|
答案 0 :(得分:0)
所以基本上每次都有一个" on"记录,它打开,否则关闭?
这里有一个与此问题略有不同的方法,每次" on"循环开始,并在结束时加-1。然后我们可以使用运行总计作为状态,当状态为0时,它会关闭,否则它会打开:
select Date,
sum(oncounter) over (order by Date) as onstat,
sum(offcounter) over (order by Date) as offstat
from (
select StartDate as Date,
case when status = 'on' then 1 else 0 end oncounter,
case when status = 'off' then 1 else 0 end offcounter
from Dates
union all
select EndDate as Date,
case when status = 'on' then -1 else 0 end oncounter,
case when status = 'off' then -1 else 0 end offcounter
from Dates
) TMP
编辑:还为off -states添加了计数器。它的工作方式与" on"相同。计数器,当两者都为0时,状态既不开启也不关闭。
最后的结果,似乎可以做到,虽然它看起来不再那么好了,但至少它不是递归的:)
select
Date as StartDate,
lead(Date, 1, '21000101') over (order by Date) as EndDate,
case onstat
when 0 then
case when offstat > 0 then 'Off' else 'N/A' end
else 'On' end as State
from (
select
Date,
onstat, prevon,
offstat, prevoff
from (
Select
Date,
onstat,
lag(onstat, 1, 0) over (order by Date) as prevon,
offstat,
lag(offstat, 1, 0) over (order by Date) as prevoff
from (
select
Date,
sum(oncounter) over (order by Date) as onstat,
sum(offcounter) over (order by Date) as offstat
from (
select
StartDate as Date,
case when status = 'on' then 1 else 0 end oncounter,
case when status = 'off' then 1 else 0 end offcounter
from
Dates
union all
select
EndDate as Date,
case when status = 'on' then -1 else 0 end oncounter,
case when status = 'off' then -1 else 0 end offcounter
from
Dates
) TMP
) TMP2
) TMP3
where (onstat = 1 and prevon = 0)
or (onstat = 0 and prevon = 1)
or (onstat = 0 and offstat = 1 and prevoff = 0)
or (onstat = 0 and offstat = 0 and prevoff = 1)
) TMP4
窗口函数有很多派生表,只有状态更改到结果集中,因此潜在客户可以选择正确的日期。有可能摆脱其中一些。
答案 1 :(得分:0)
这是2008年最简单的版本,我能够弄清楚:
; with Data (Date) as (
select StartDate from Dates
union
select EndDate from Dates),
Ranges (StartDate, Status) as (
select D.Date, D2.Status
from Data D
outer apply (
select top 1 D2.Status
from Dates D2
where D2.StartDate <= D.Date and D2.EndDate > D.Date
order by case when Status = 'on' then 1 else 2 end
) D2)
select R.StartDate,
(select min(D.Date) from Data D where D.Date > R.StartDate) as EndDate,
Status
from Ranges R
order by R.StartDate
即使状态与之前相同,它也会从每个开始/结束点开始返回新行。没有找到任何简单的方法来组合它们。
编辑:将第一个CTE更改为此将合并行:
; with Data (Date) as (
select distinct StartDate from Dates D1
where not exists (Select 1 from Dates D2
where D2.StartDate < D1.StartDate and D2.EndDate > D1.StartDate and
Status = 'on')
union
select distinct EndDate from Dates D1
where not exists (Select 1 from Dates D2
where D2.StartDate < D1.EndDate and D2.EndDate > D1.EndDate and
Status = 'on')
),