我有一个看起来像这样的数据集
id sid start end
34011 10017 2006-01-11 2006-06-28
66 10017 2006-10-24 NULL
67 10017 2007-04-15 NULL
68 10017 2007-10-15 2007-12-31
71 10017 2008-04-15 NULL
72 10017 2008-10-15 NULL
69 10017 2009-04-16 NULL
70 10017 2009-10-15 2010-03-01
33022 10019 2005-09-01 2005-10-03
35425 10019 2006-03-15 2006-09-15
35555 10019 2006-10-01 NULL
79 10019 2006-12-01 2007-04-12
88 10019 2010-01-02 NULL
99 10019 2010-07-02 NULL
我需要一个查询(我认为是递归的)来提取以下内容
10017 2006-01-11 2006-06-28
10017 2006-10-24 2007-12-31
10017 2008-04-15 2010-03-01
10019 2005-09-01 2005-10-03
10019 2006-03-15 2006-09-15
10019 2006-10-01 2007-04-12
10019 2010-01-02 NULL
查询的要点是我需要跨越多行的开始和结束范围
答案 0 :(得分:0)
嗯,这不是最漂亮的代码,但这将完成工作。
我的测试表名为#results
,因此您显然希望将其替换为您的真实表名。
-- First find the next endDate for any record with a null endDate
select [sid], startDate,
( select MIN(endDate)
from #results r
where r.[sid] = #results.[sid]
and r.endDate is not null
and r.endDate > #results.startDate
group by r.[sid]
) as endDate
into #nullEndDates
from #results
where #results.endDate is null
-- Then union those results with records that have an endDate
-- and get the min(startDate) for the unioned result
select [sid], min(StartDate) as startDate, endDate
from
(
select [sid], min(StartDate) as startDate, endDate
from #nullEndDates
group by [sid], endDate
union
select [sid], startDate, endDate
from #results
where #results.endDate is not null
) results
group by [sid], endDate
order by [sid], min(startDate)
我的第一次尝试是使用LEAD()
根据下一个startDate填充所有endDates。我不认为这是你想要的,但以防万一:
select [sid],
startDate,
isnull(endDate, LEAD(startDate) OVER (ORDER BY [sid])) as endDate
from #results
order by [sid], startDate
答案 1 :(得分:0)
尝试下面的sql:
这是概念:
注意:请重新检查sql(表名,字段名等)
-- Declare TempData Table
declare @tempData table
(
id int identity,
[sid] int,
start date,
[end] date
);
-- Declare TempMapping Table
declare @tempMapping table
(
id int identity,
start_id int,
end_id int
);
--Insert the data to @tempData, with new ID
insert into @tempData([sid],[start],[end])
select [sid],[start],[end] from @temp
order by [sid],[start],[end]
;
--insert The Mapping value
insert into @tempMapping(start_id,end_id)
select
start_id , end_id
from
(
select start_id, end_id
, ROW_NUMBER() over ( partition by end_id order by start_id) as xxrow
from
(
select
a.id as start_id ,bb.id as end_id
,ROW_NUMBER() over(partition by a.id order by a.id) as xrow
from
(
select b.id, b.[sid],b.[start]
from @tempData b
where b.[end] is null
) a
left join
(
select b.id, b.[sid],b.[start],b.[end]
from @tempData b
where b.[end] is not null
) bb on a.[sid] = bb.[sid] and a.[id]< bb.id
group by
a.id, a.[sid],a.[start]
,bb.[id]
) c
where c.xrow = 1
) d
where d.xxrow =1
order by start_id, end_id
;
/*
select * from @tempMapping
--Table Mapping Result:
id start_id end_id
----------- ----------- -----------
1 2 4
2 5 8
3 11 12
4 13 NULL
*/
--Result Query
select
e.[id],e.[sid], e.[start],e.[end]
from @tempData e
left join @tempMapping f on f.end_id = e.id
where e.[end] is not null and f.id is null
union
select
start_id as id, b.sid, b.start, c.[end]
from @tempMapping a
left join @tempData b on a.start_id = b.id
left join @tempData c on a.end_id = c.id
结果表:
id sid start end
----------- ----------- ---------- ----------
1 10017 2006-01-11 2006-06-28
2 10017 2006-10-24 2007-12-31
5 10017 2008-04-15 2010-03-01
9 10019 2005-09-01 2005-10-03
10 10019 2006-03-15 2006-09-15
11 10019 2006-10-01 2007-04-12
13 10019 2010-01-02 NULL