2014-04-04 47 views
0

加入記錄有包含數據的表測試,如下圖所示:來自同一個表

id id1 id2 id3  date1 
1 1 2 2500 2010-09-30 00:00:00.000 
2 1 2 4700 2005-01-01 00:00:00.000 
3 1 2 4700 2009-08-01 00:00:00.000 
4 1 3 2500 2010-09-30 00:00:00.000 
5 1 3 4700 2003-02-01 00:00:00.000 
6 1 8 4000 2007-04-01 00:00:00.000 
7 1 8 4000 2013-09-01 00:00:00.000 
8 1 8 4060 2007-04-01 00:00:00.000 
9 1 8 8500 2010-09-30 00:00:00.000 

我需要做的就是爲了這個數據的格式如下:

id1 id2 id3  date1     date2 
1 2 2500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997 
1 2 4700 2005-01-01 00:00:00.000 2009-07-31 00:00:00.000 
1 2 4700 2009-08-01 00:00:00.000 9999-12-31 23:59:59.997 
1 3 2500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997 
1 3 4700 2003-02-01 00:00:00.000 9999-12-31 23:59:59.997 
1 8 4000 2007-04-01 00:00:00.000 2013-08-31 00:00:00.000 
1 8 4000 2013-09-01 00:00:00.000 9999-12-31 23:59:59.997 
1 8 4060 2007-04-01 00:00:00.000 9999-12-31 23:59:59.997 
1 8 8500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997 

使用以下邏輯:

  • 如果同一個id1,id2和id3只有一條記錄,我們使用date1的原始日期,我們使用最大的d在日期2的sql server(9999-12-31)中可用。
  • 如果同一個id1,id2和id3有多個記錄,我們仍然保留date1的原始日期,並且我們使用date2從原來的日期字段減去下一個記錄的1天。最後一條記錄還將使用date2中sql server(9999-12-31)中的最大日期。

我設法構建以下查詢,但因爲它帶來了一些無效的記錄,它並不完美:

select * from 
(select 
t1.id1,t1.id2,t1.id3,t1.date1, 
case 
when t1.date1=t2.date1 then CONVERT(DATETIME, '12/31/9999 23:59:59.997') 
else DATEADD(day, -1, t2.date1) 
end as date2 
from test t1 
inner join test t2 
on t1.id1=t2.id1 and t1.id2=t2.id2 and t1.id3=t2.id3 
) sub 
where date2>=date1 
order by id1,id2,id3,date1 asc 

查詢的結果是:

id1 id2 id3  date1     date2 
1 2 2500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997 
1 2 4700 2005-01-01 00:00:00.000 9999-12-31 23:59:59.997 * 
1 2 4700 2005-01-01 00:00:00.000 2009-07-31 00:00:00.000 
1 2 4700 2009-08-01 00:00:00.000 9999-12-31 23:59:59.997 
1 3 2500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997 
1 3 4700 2003-02-01 00:00:00.000 9999-12-31 23:59:59.997 
1 8 4000 2007-04-01 00:00:00.000 9999-12-31 23:59:59.997 * 
1 8 4000 2007-04-01 00:00:00.000 2013-08-31 00:00:00.000 
1 8 4000 2013-09-01 00:00:00.000 9999-12-31 23:59:59.997 
1 8 4060 2007-04-01 00:00:00.000 9999-12-31 23:59:59.997 
1 8 8500 2010-09-30 00:00:00.000 9999-12-31 23:59:59.997 

正如你所看到的,用*標記的記錄沒有必要,但我不知道如何擺脫那些行。

+0

爲什麼你一個減去一天嗎?如果你正在處理時間戳,你將錯過24小時的數據。最好將'date2'保留爲另一個值,以啓用[簡單的結束日期查詢](http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do-between- and-the-devil-have-in-common.aspx) - 沒有結束日期這樣的事情,只有下一個狀態的開始。我還會在沒有已知結束日期的情況下使用'null',而不是高版本(可能會在未來的版本中更改!) –

回答

0

這應該這樣做:

select id1,id2,id3, date1, 
isnull(lead(date1) over(partition by id1,id2,id3 order by date1)-1, '99991231') as date2 
from test 
0

嘗試這樣的事情

SELECT t1.id1, t1.id2, t1.id3, t1.date1 as date1, 
    ISNULL(t2.date1, CONVERT(DATETIME, '12/31/9999 23:59:59.997')) as date2 
FROM test t1 
    LEFT JOIN test t2 ON t1.id1 = t2.id1 AND t1.id2 = t2.id2 AND t1.id3 = t2.id3 
     AND t1.id < t2.id 
ORDER BY t1.id1, t1.id2, t1.id3, date1, date2 
+0

它也會帶來無效記錄 –