获取最短和最长日期

时间:2015-09-04 20:02:13

标签: tsql group-by common-table-expression partition

我有一组数据(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)从此项目从一个地方移动到另一个地方开始,直到从底部开始的第5行(orig_counter = 30003)。

所以我可以确定一个人有这个项目的时间长度,我需要有这样的结果,我显示原始计数器,结束计数器(如果有的话)最小开始日期和最大停止日期。 / p>

    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

1 个答案:

答案 0 :(得分:0)

此查询以prev_counter = 0开头递归循环遍历orig_counter和prev_counter:

-- 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