按连续日期SQL Server对应的所有列分组

时间:2018-02-15 21:01:37

标签: sql sql-server

我在SQL Server 2012中工作并拥有如下数据集:

ID    DATE1         TMT
-----------------------
121   2016-04-01     B
121   2016-04-04     A
121   2016-04-06     A
121   2016-04-08     A
121   2016-04-11     B
121   2016-04-13     B
121   2016-04-15     A
122   2016-03-14     A
122   2016-03-16     A
122   2016-03-18     B
122   2016-03-21     B
122   2016-03-24     A
122   2016-03-29     A

期望的输出:

ID    BEGIN_DATE    END_DATE     TMT  DAY_COUNT
-----------------------------------------------
121   2016-04-01    2016-04-01    B     1
121   2016-04-04    2016-04-08    A     4
121   2016-04-11    2016-04-13    B     2
121   2016-04-15    2016-04-15    A     1
122   2016-03-14    2016-03-16    A     2
122   2016-03-18    2016-03-21    B     3
122   2016-03-24    2016-03-29    A     5

我现在的代码:

;WITH S AS 
(
     SELECT 
         ID, MIN(DATE1) BEGIN_DATE, MAX(DATE1) END_DATE, TMT
     FROM 
         MyTable
     GROUP BY 
         id, TMT
)
SELECT 
    *, 
    CASE WHEN DATEDIFF(d, BEGIN_DATE, END_DATE) = 0 
            THEN 1 
            ELSE DATEDIFF(d, BEGIN_DATE, END_DATE) 
    END DAY_COUNT 
FROM 
    S 

代码生成如下结果:

ID    BEGIN_DATE    END_DATE     TMT  DAY_COUNT
------------------------------------------------
121   2016-04-01    2016-04-13    B     12
121   2016-04-04    2016-04-15    A     11
122   2016-03-14    2016-03-29    A     15
122   2016-03-18    2016-03-21    B     3

不确定如何从此处获得所需的输出。任何帮助将不胜感激!

谢谢!

2 个答案:

答案 0 :(得分:1)

这是一个差距和岛屿问题尝试这样

select t.id, 
       min(date1) as begin_date, 
       max(date1) as end_date, 
       datediff(day, min(date1), max(date1)) day_count,
       t.TMT
from
(
    select *, row_number() over (partition by id, TMT order by date1) - 
              row_number() over (partition by id order by date1) grn
    from s
) t
group by t.id, t.TMT, grn

关键是嵌套子查询,其中有两个row_number()函数,以隔离TMT每个id的连续出现。获得grn值后,其余部分就很简单group by

答案 1 :(得分:0)

@ZLK的回答对我来说非常合适!谢谢@ZLK! 这是代码,如果有其他人需要它 -

select id, min(date1), max(date1), tmt, datediff(day, min(date1), max(date1)) 
from (select *, rn = row_number() over (order by id, date1) - row_number() 
over (partition by tmt order by id, date1) from mytable) as t group by id, 
 tmt, rn;