将数据行转换为日期范围

时间:2018-02-12 11:21:20

标签: sql sql-server

我希望将数据行转换为sql中的日期范围。 以下是样本数据

#Slno   MonthDate   System#
1   7/1/2017    SystemA
1   8/1/2017    SystemA
1   9/1/2017    SystemB
1   10/1/2017   SystemB
1   11/1/2017   SystemB
1   12/1/2017   SystemA
1   1/1/2018    SystemA
1   2/1/2018    SystemA
1   3/1/2018    SystemB
2   12/1/2017   SystemA
2   1/1/2018    SystemB
3   2/1/2018    SystemA
4   3/1/2018    SystemB

和期望的输出是

#Slno   StartDate   EndDate System#
1   7/1/2017    8/1/2017    SystemA
1   9/1/2017    11/1/2017   SystemB
1   12/1/2017   3/1/2018    SystemA
2   12/1/2017   12/1/2017   SystemA
2   1/1/2018    1/1/2018    SystemB
3   2/1/2018    2/1/2018    SystemA
4   3/1/2018    3/1/2018    SystemB

2 个答案:

答案 0 :(得分:3)

您可以使用"行号的差异"方法:

select slno, system, min(date), max(date)
from (select t.*,
             row_number() over (partition by slno order by date) as seqnum_s,
             row_number() over (partition by slno, system order by date) as seqnum_ss
      from t
     ) t
group by slno, system, (seqnum_s - seqnum_ss);

这个逻辑有点棘手。根据我的经验,您可以运行子查询并盯着结果。您应该能够看到行号的差异如何定义相邻行中由相等值定义的组。

答案 1 :(得分:0)

这是使用窗口函数的另一种方法

;WITH cte
     AS (SELECT *,
                Grp = Sum(CASE WHEN System = prev_System THEN 0 ELSE 1 END)
                        OVER(partition BY Slno ORDER BY MonthDate)
         FROM   (SELECT *,
                        prev_System = Lag(System)OVER(partition BY Slno ORDER BY MonthDate)
                 FROM   Yourtable) a)
SELECT Slno, System, Min(MonthDate), Max(MonthDate)
FROM   cte
GROUP  BY Slno, System, Grp 

Lag(System)OVER(partition BY Slno ORDER BY MonthDate)可帮助您识别每个月份的先前系统

Sum(CASE WHEN System = prev_System THEN 0 ELSE 1 END) OVER(partition BY Slno ORDER BY MonthDate)可帮助您在上一个系统和当前系统相同时创建组

注意:这可以从Sql Server 2012

开始