2015-09-04 13 views
1

У меня есть набор данных (T-SQL 2012), который содержит номер позиции, orig_counter, prev_counter, start_date и дату остановки. Что мне нужно сделать, так это получить 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) начинается там, где этот элемент не перемещается из одного места в другое до строки, которая пятые от дна (orig_counter = 30003).

Чтобы я мог определить время, в течение которого человек имел этот предмет, мне нужно иметь такие результаты, когда я показываю оригинал nal counter, end counter (если есть), минимальная дата начала и максимальная дата остановки.

 
    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. Я пытался использовать соединение по-прежнему, но просто не мог понять это правильно. Я попробую это, как только смогу. –