2014-04-29 74 views
0

我有一個拉動查詢以下SQL服務器 - 遞歸查詢的日期

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 

要點的數據集,看起來像這樣

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 

我需要一個查詢(我認爲遞歸)是我需要一個跨越多行的開始和結束範圍

回答

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 
0

試試下面的SQL:

這是概念:

  1. 修復的id值,此刻這是一團糟。
  2. 創建一個映射表來幫助我們獲得結果。

注:請重新檢查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