【问题标题】:Get min and max dates获取最小和最大日期
【发布时间】:2015-09-04 20:02:13
【问题描述】:

我有一组数据 (T-SQL 2012),其中包含项目编号、orig_counter、prev_counter、start_date 和停止日期。如果项目已从一个地方移动到另一个地方,我需要做的是获取最小 start_date 和最大 stop_date(prev_counter 将在此移动中填充 orig_counter。如果 prev_counter 为 0,则它没有先前的移动.

我的数据如下所示:

项目 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)。

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

【问题讨论】:

  • 我认为这是一个空白和孤岛问题。您需要识别并折叠我认为 prev_counter 非零的相邻集群。
  • 我想过,但无法弄清楚,因为计数器不是连续的并且有间隙。
  • 但是您可以很容易地通过计数器生成行号排序,然后按顺序排列。

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


【解决方案1】:

此查询以 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

【讨论】:

  • 感谢朱利安的建议。我试图使用之前的连接,但从来没有完全正确。我会尽快尝试一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 1970-01-01
  • 2012-07-16
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多