繁体   English   中英

获取 T-SQL 中连续值的最大和最小日期

[英]Get Max And Min dates for consecutive values in T-SQL

我有一个如下所示的日志表,并希望通过获取每个 Id 的连续状态值的最小开始日期和最大结束日期来简化它。 我尝试了很多窗口函数组合,但没有运气。

这就是我所拥有的:

在此处输入图片说明

这是想看到的:

在此处输入图片说明

尝试以下查询。 首先按 StartDate 对数据进行排序并生成一个序列(rid)。 然后你递归 cte 来获取每个组 (id,status) 的第一行 (rid=1),并递归获取下一行并比较开始/结束日期。

;WITH cte_r(id,[Status],StartDate,EndDate,rid)
AS
(
SELECT id,[Status],StartDate,EndDate, ROW_NUMBER() OVER(PARTITION BY Id,[Status] ORDER BY StartDate) AS rid
FROM log_table 
),
cte_range(id,[Status],StartDate,EndDate,rid)
AS
(
  SELECT id,[Status],StartDate,EndDate,rid
  FROM cte_r
  WHERE rid=1
  UNION ALL
  SELECT p.id, p.[Status], CASE WHEN c.StartDate<p.EndDate THEN p.StartDate ELSE c.StartDate END AS StartDate, c.EndDate,c.rid
  FROM cte_range p
  INNER JOIN cte_r c
  ON p.id=c.id
  AND p.[Status]=c.[Status]
  AND p.rid+1=c.rid
 )
 SELECT id,[Status],StartDate,MAX(EndDate) AS EndDate FROM cte_range GROUP BY id,StartDate ;

这是一个典型的间隙和孤岛问题。 您想要聚合具有相同IdStatus的连续记录组。

不需要递归,这是使用窗口函数解决它的一种方法:

select
    Id,
    Status,
    min(StartDate) StartDate,
    max(EndDate) EndDate
from (
    select
        t.*,
        row_number() over(partition by id order by StartDate) rn1,
        row_number() over(partition by id, status order by StartDate) rn2
    from mytable t
) t
group by
    Id,
    Status,
    rn1 - rn2
order by Id, min(StartDate)

该查询通过对两个不同分区(通过Id以及通过IdStatus )的记录进行排名来工作。 排名之间的差异为您提供了每条记录所属的组。 您可以独立运行子查询以查看它返回的内容并理解逻辑。

DB Fiddle 上的演示

Id | Status | StartDate           | EndDate            
-: | :----- | :------------------ | :------------------
 1 | B      | 07/02/2019 00:00:00 | 18/02/2019 00:00:00
 1 | C      | 18/02/2019 00:00:00 | 10/03/2019 00:00:00
 1 | B      | 10/03/2019 00:00:00 | 01/04/2019 00:00:00
 2 | A      | 05/02/2019 00:00:00 | 22/04/2019 00:00:00
 2 | D      | 22/04/2019 00:00:00 | 05/05/2019 00:00:00
 2 | A      | 05/05/2019 00:00:00 | 30/06/2019 00:00:00

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM