SQL日期选择

时间:2018-04-22 20:51:40

标签: sql sql-server tsql date

我有一个OPL_Dates表,其开始日期和结束日期如下:

dbo.OPL_Dates
ID       Start_date       End_date
--------------------------------------
12345    1975-01-01       2001-12-31
12345    1989-01-01       2004-12-31
12345    2005-01-01       NULL
12345    2007-01-01       NULL
12377    2009-06-01       2009-12-31
12377    2013-02-07       NULL
12377    2010-01-01       2012-01-01
12489    2011-12-31       NULL
12489    2012-03-01       2012-04-01

我正在寻找的输出是:

ID       Start_date       End_date
-------------------------------------
12345    1975-01-01       2004-12-31
12345    2005-01-01       NULL
12377    2009-06-01       2009-12-31
12377    2010-01-01       2012-01-01
12377    2013-02-07       NULL
12489    2011-12-31       NULL

基本上,我想显示OPL期间(IF Any)之间的差距,否则我需要最小开始日期和最后结束日期,对于特定ID.NULL表示开放日期可以转换为“9999” -12-31" 。

1 个答案:

答案 0 :(得分:1)

以下几乎可以满足您的需求:

with p as (
      select v.*, sum(inc) over (partition by v.id order by v.dte) as running_inc
      from t cross apply
           (values (id, start_date, 1),
                   (id, coalesce(end_date, '2999-12-31'), -1)
           ) v(id, dte, inc)
     )
select id, min(dte), max(dte)
from (select p.*, sum(case when running_inc = 0 then 1 else 0 end) over (partition by id order by dte desc) as grp
      from p
     ) p
group by id, grp;

请注意,它会将“无限”结束日期从NULL更改为2999-12-31。这是一种方便,因为NULL在SQL Server升序排序中首先命令。

Here是一个SQL小提琴。

这是做什么的?它将日期拆分为单个列,其中1 / -1标志(inc)表示记录是开始还是结束。然后,该标志的运行总和表示应该组合的组。当运行总和为0时,组已结束。要在正确的组中包含结束日期,需要反向运行总和 - 但这是一个细节。