2015-09-04 114 views
1

我有一組包含項目編號,orig_counter,prev_counter,start_date和停止日期的數據(T-SQL 2012)。我需要做的是獲得min start_date和max stop_date,如果物品已經從一個地方移動到另一個地方(prev_counter將在這個移動中用orig_counter填充。如果prev_counter是0,那麼它沒有先前移動。獲取最小和最大日期

這裏是我的數據是什麼樣子:

 
    item orig_counter prev_counter start_date stop_date 
    --------------------------------------------------------------- 
    AB108  8194   0   2001-12-03 2001-12-10 
    AB108  8569   0   2002-01-04 2002-01-22 
    AB108  9233   0   2002-02-01 2002-02-01 
    AB108  12365  0   2002-07-08 2004-02-29 
    AB108  24602  12365  2002-07-08 2004-03-09 
    AB108  24855  24602  2002-07-08 2004-03-23 
    AB108  24945  24855  2002-07-08 2004-03-29 
    AB108  25042  24945  2002-07-08 2004-04-04 
    AB108  25106  25042  2002-07-08 2004-04-11 
    AB108  25226  25106  2002-07-08 2004-04-22 
    AB108  25569  25226  2002-07-08 2004-04-28 
    AB108  25724  25569  2002-07-08 2004-06-01 
    AB108  26749  25724  2002-07-08 2004-06-30 
    AB108  27187  26749  2002-07-08 2004-07-11 
    AB108  27336  27187  2002-07-08 2004-08-15 
    AB108  28272  27336  2002-07-08 2004-08-24 
    AB108  28329  28272  2002-07-08 2004-11-07 
    AB108  29831  28329  2002-07-08 2004-11-08 
    AB108  30003  29831  2002-07-08 2005-08-03 
    AB108  36618  0   2005-09-19 2005-10-19 
    AB108  37613  0   2005-11-07 2005-11-07 
    AB108  37756  0   2005-11-10 2005-11-28 
    AB108  38979  0   2006-01-25 2006-08-01 

正如你所看到的第4行(orig_counter = 12365)從哪裏開始這個項目從一個地方移動到另一個,直到那就是5日從底部的行(這樣我可以確定一個人有這個項目的時間長度,我需要有這樣的結果,我在哪裏顯示原始的最終計數器(如果有的話)最小開始日期和最大停止日期。

 
    item  orig_counter end_counter start_date stop_date 
    ---------- ------------ ------------ ---------- ---------- 
    AB108  8194   0   2001-12-03 2001-12-10 
    AB108  8569   0   2002-01-04 2002-01-22 
    AB108  9233   0   2002-02-01 2002-02-01 
    AB108  12365  30003  2002-07-08 2005-08-03 
    AB108  36618  0   2005-09-19 2005-10-19 
    AB108  37613  0   2005-11-07 2005-11-07 
    AB108  37756  0   2005-11-10 2005-11-28 
    AB108  38979  0   2006-01-25 2006-08-01 
+0

我認爲這是一個間隙和島嶼問題。您需要確定並摺疊prev_counter非零的相鄰羣集,我認爲。 – shawnt00

+0

我考慮過這個問題,但由於計數器並不連續並且有差距,所以無法弄清楚。 –

+0

但是你可以很容易地通過計數器產生一個行號順序,然後順序。 – shawnt00

回答

0

該查詢通過orig_counter和prev_counter遞歸循環開始prev_counter = 0:

-- Sample data 
declare @data table(item char(5), orig_counter int, prev_counter int, start_date datetime, stop_date datetime); 
insert into @data(item, orig_counter, prev_counter, start_date, stop_date) values 
    ('AB108', 8194, 0, '2001-12-03', '2001-12-10') 
    , ('AB108', 8569, 0, '2002-01-04', '2002-01-22') 
    , ('AB108', 9233, 0, '2002-02-01', '2002-02-01') 
    , ('AB108', 12365, 0, '2002-07-08', '2004-02-29') 
    , ('AB108', 24602, 12365, '2002-07-08', '2004-03-09') 
    , ('AB108', 24855, 24602, '2002-07-08', '2004-03-23') 
    , ('AB108', 24945, 24855, '2002-07-08', '2004-03-29') 
    , ('AB108', 25042, 24945, '2002-07-08', '2004-04-04') 
    , ('AB108', 25106, 25042, '2002-07-08', '2004-04-11') 
    , ('AB108', 25226, 25106, '2002-07-08', '2004-04-22') 
    , ('AB108', 25569, 25226, '2002-07-08', '2004-04-28') 
    , ('AB108', 25724, 25569, '2002-07-08', '2004-06-01') 
    , ('AB108', 26749, 25724, '2002-07-08', '2004-06-30') 
    , ('AB108', 27187, 26749, '2002-07-08', '2004-07-11') 
    , ('AB108', 27336, 27187, '2002-07-08', '2004-08-15') 
    , ('AB108', 28272, 27336, '2002-07-08', '2004-08-24') 
    , ('AB108', 28329, 28272, '2002-07-08', '2004-11-07') 
    , ('AB108', 29831, 28329, '2002-07-08', '2004-11-08') 
    , ('AB108', 30003, 29831, '2002-07-08', '2005-08-03') 
    , ('AB108', 36618, 0, '2005-09-19', '2005-10-19') 
    , ('AB108', 37613, 0, '2005-11-07', '2005-11-07') 
    , ('AB108', 37756, 0, '2005-11-10', '2005-11-28') 
    , ('AB108', 38979, 0, '2006-01-25', '2006-08-01'); 

-- Recursive query 
with list(n, item, orig_counter, prev_counter, start_date, stop_date) as (
    Select 0, item, orig_counter, orig_counter, start_date, stop_date From @data Where prev_counter = 0 
    Union All 
    Select l.n+1, l.item, l.orig_counter, d.orig_counter, l.start_date, d.stop_date From list as l 
    Inner Join @data as d on l.prev_counter = d.prev_counter and l.item= d.item 
) 
Select l.item, l.orig_counter, prev_counter = case when m.mx > 0 then l.prev_counter else 0 end, l.start_date, l.stop_date 
From list l 
Inner Join (Select mx = max(n), item, orig_counter From list Group By item, orig_counter) as m 
    On m.item = l.item and m.orig_counter = l.orig_counter and m.mx = l.n 
Order By l.item, l.orig_counter 
OPTION (MAXRECURSION 0); 

輸出:

item | orig_counter | prev_counter | start_date    | stop_date 
AB108 | 8194   | 0   | 2001-12-03 00:00:00.000 | 2001-12-10 00:00:00.000 
AB108 | 8569   | 0   | 2002-01-04 00:00:00.000 | 2002-01-22 00:00:00.000 
AB108 | 9233   | 0   | 2002-02-01 00:00:00.000 | 2002-02-01 00:00:00.000 
AB108 | 12365  | 30003  | 2002-07-08 00:00:00.000 | 2005-08-03 00:00:00.000 
AB108 | 36618  | 0   | 2005-09-19 00:00:00.000 | 2005-10-19 00:00:00.000 
AB108 | 37613  | 0   | 2005-11-07 00:00:00.000 | 2005-11-07 00:00:00.000 
AB108 | 37756  | 0   | 2005-11-10 00:00:00.000 | 2005-11-28 00:00:00.000 
AB108 | 38979  | 0   | 2006-01-25 00:00:00.000 | 2006-08-01 00:00:00.000 
+0

感謝Julien的建議。我試圖通過事先使用連接,但永遠不可能完全正確。我會盡快嘗試。 –