2012-06-16 103 views
2

我需要查找定義爲範圍的開始日期和結束日期:開始日期是第一個日期,結束日期是第二個日期,其中後續日期爲兩個月或在結束日期之後更多。可以有多個可能的範圍在非連續範圍內查找開始日期和結束日期

我有這樣一個表結構:

ID  int identity(1,1), 
fk_ID  char(9), 
dateField datetime 

的數據是這樣的:

1  a  2012-01-01 
2  a  2012-01-05 
3  a  2012-01-12 
4  b  2012-02-01 
5  a  2012-04-01 
6  b  2012-05-01 
7  a  2012-05-30 

預期結果會是什麼樣子:

fk_id startdate enddate 
a  2012-01-01 2012-01-12 
a  2012-04-01 2012-05-30 
b  2012-02-01 2012-02-01 
b  2012-05-01 null 

編輯: 通過執行以下操作:

CREATE TABLE #temp 
(
    autonum  int  identity(1,1), 
    id   char(9), 
    sd   datetime 
) 

insert into #temp (id, sd) values ('a', '2012-01-01') 
insert into #temp (id, sd) values ('a', '2012-01-05') 
insert into #temp (id, sd) values ('a', '2012-01-12') 
insert into #temp (id, sd) values ('a', '2012-03-01') 
insert into #temp (id, sd) values ('a', '2012-04-03') 
insert into #temp (id, sd) values ('a', '2012-06-06') 
insert into #temp (id, sd) values ('b', '2012-02-12') 
insert into #temp (id, sd) values ('b', '2012-02-15') 
insert into #temp (id, sd) values ('b', '2012-03-01') 
insert into #temp (id, sd) values ('b', '2012-04-03') 
insert into #temp (id, sd) values ('b', '2012-06-01') 

select t1.id, null as previousend, min(t1.sd) as nextstart 
from #temp t1 
group by t1.id 
union 
select t1.id, t1.sd as enddate, (select min(t2.sd) from #temp t2 where t1.id=t2.id and t2.sd>t1.sd) as nextstart 
from #temp t1 
where (select min(t2.sd) from #temp t2 where t1.id=t2.id and t2.sd>t1.sd) >= dateadd(month, 2, t1.sd) 
union 
select t1.id, max(t1.sd), null 
from #temp t1 
group by t1.id 

drop table #temp 

我能得到的輸出是這樣的:

id  previousend    nextstart 
--------- ----------------------- ----------------------- 
a   NULL     2012-01-01 00:00:00.000 
a   2012-04-03 00:00:00.000 2012-06-06 00:00:00.000 
a   2012-06-06 00:00:00.000 NULL 
b   NULL     2012-02-12 00:00:00.000 
b   2012-06-01 00:00:00.000 NULL 

這是非常接近,但理想範圍的開始和結束日期將是對行。

+0

我想你的意思是_...並且結束日期是**開始日期**之後的後續日期是兩個月或更長時間的第一個日期,對嗎? – alf

+0

@alfonso不幸的是,描述是準確的,如果有點混亂。數據示例有望澄清情況。 – spizotfl

+0

您已經在第二組不同的樣本數據中顯示了「非常接近」的內容。你能否在這種情況下顯示你真正想要的結果,而不是用另一個令人困惑的單詞問題模糊地描述它? –

回答

1

嘗試二號這是對Fiddle,是遠離優雅,但似乎從不是空的結束日期的最後一條記錄除了工作:

CREATE TABLE temp 
(
    id   char(9), 
    d   datetime 
); 

insert into temp (id, d) values ('a', '2012-01-01'); 
insert into temp (id, d) values ('a', '2012-01-05'); 
insert into temp (id, d) values ('a', '2012-01-12'); 
insert into temp (id, d) values ('a', '2012-04-01'); 
insert into temp (id, d) values ('a', '2012-05-30'); 
insert into temp (id, d) values ('b', '2012-02-01'); 
insert into temp (id, d) values ('b', '2012-05-01'); 


SELECT 
    x.id , 
    min(x.sd) sd , 
    x.ed 
FROM 
    (SELECT 
     a.id , 
     a.sd , 
     max(a.ed) ed 
    FROM 
     ( 
     SELECT 
      j.id , 
      j.d sd , 
      q.D ed 
     FROM temp j 
      JOIN temp q 
      ON 
      j.id = q.id 
      AND j.d <= q.d 
     GROUP BY j.id , 
      j.d , 
      q.d 
    ) a 
    WHERE datediff(m,a.sd,a.ed)<=2 
    GROUP BY a.id , 
     a.sd 
     )x 
GROUP BY x.id , 
     x.ed 
ORDER BY x.id , 
     min(x.sd) , 
     x.ed 
+0

樣本小提琴第一個結果顯示開始日期2012年1月1日,結束日期爲2012年9月1日。它應該是開始日期2012年1月1日,結束日期爲2012年1月2日。開始日期2012年9月1日,結束日期爲null。 – spizotfl

+0

YEP - 道歉我誤解了這個問題;我不知道如何回答這個問題,並期待看到最後回答 – whytheq

+0

繼續擺弄,但問題是我的星期天下午真的搞砸了:http://sqlfiddle.com/#!3/b3f67/15 – whytheq

2

這是我最好的猜測給出的所有更改這個問題。我仍然發現這個問題非常混亂,分裂,並且兩個案例的預期結果似乎不匹配。與此查詢:

;WITH x AS 
(
    SELECT a.id, sd = a.sd, ed = b.sd, rn1 = ROW_NUMBER() OVER 
    (PARTITION BY a.id, a.sd ORDER BY a.sd) 
    FROM #temp AS a 
    LEFT OUTER JOIN #temp AS b 
    ON a.id = b.id 
    AND b.sd >= a.sd 
    AND b.sd <= DATEADD(MONTH, 2, a.sd) 
), 
y AS 
(SELECT id, sd, 
    ed = (SELECT MAX(ed) FROM x AS x2 
    WHERE x.id = x2.id AND x2.sd <= DATEADD(MONTH, 2, x.sd) 
) 
FROM x 
WHERE rn1 = 1 
), 
z AS 
(
    SELECT id, sd = MIN(sd), ed 
    FROM y GROUP BY id, ed 
) 
SELECT id, sd, ed /* = CASE 
    WHEN ed > sd OR (sd = ed AND NOT EXISTS 
    (SELECT 1 FROM z AS z2 WHERE z2.id = z.id AND z.sd > z2.sd)) THEN ed END 
*/ 
FROM z 
ORDER BY id, sd; 

你的第一組數據的結果:

INSERT #temp (id, sd) VALUES 
('a','2012-01-01'), 
('a','2012-01-05'), 
('a','2012-01-12'), 
('b','2012-02-01'), 
('a','2012-04-01'), 
('b','2012-05-01'), 
('a','2012-05-30'); 

如下:

id sd   ed 
a 2012-01-01 2012-01-12 
a 2012-04-01 2012-05-30 
b 2012-02-01 2012-02-01 
b 2012-05-01 2012-05-01 

而對於第二組:

insert into #temp (id, sd) values ('a', '2012-01-01') 
insert into #temp (id, sd) values ('a', '2012-01-05') 
insert into #temp (id, sd) values ('a', '2012-01-12') 
insert into #temp (id, sd) values ('a', '2012-03-01') 
insert into #temp (id, sd) values ('a', '2012-04-03') 
insert into #temp (id, sd) values ('a', '2012-06-06') 
insert into #temp (id, sd) values ('b', '2012-02-12') 
insert into #temp (id, sd) values ('b', '2012-02-15') 
insert into #temp (id, sd) values ('b', '2012-03-01') 
insert into #temp (id, sd) values ('b', '2012-04-03') 
insert into #temp (id, sd) values ('b', '2012-06-01') 

如下:

id sd   ed 
a 2012-01-01 2012-04-03 
a 2012-06-06 2012-06-06 
b 2012-02-12 2012-06-01 

如果取消對CASE塊的註釋,則會在開始日期和結束日期相同的結束日期獲得NULL值。正如我多次提出的那樣,你的問題是分裂的,你的期望結果似乎不匹配,所以我不確定正確的答案是什麼。

+0

這完全按照我的需要工作。你能否推薦一個CTE源代碼來幫助我理解這裏發生的事情?再次感謝 – spizotfl

+0

CTE不過是一個派生表,但語法允許您在隨後的查詢中多次引用它。我會說[在這裏](http://www.learnkey.com/elearning/PDFs/Common%20Table%20Expressions.pdf)和[這裏](http://www.simple-talk.com/sql/t -sql-programming/sql-server-cte-basics /)是很好的開始。 –

+0

我選擇這個答案還爲時過早。我添加了1行:ID = 7 FK_ID = a dateField ='2012-02-01'。從另一個月份添加日期會拋出所有輸出。 – spizotfl

相關問題