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

获取T-SQL中连续值的最大和最小日期,sql,sql-server,window-functions,gaps-and-islands,date-arithmetic,Sql,Sql Server,Window Functions,Gaps And Islands,Date Arithmetic,我有一个如下所示的日志表,希望通过获取每个Id的连续状态值的最小开始日期和最大结束日期来简化它。我尝试了许多窗口函数组合,但没有成功 这就是我所拥有的: 这就是我想看到的: 请尝试以下查询。首先按StartDate对数据进行排序并生成序列rid。然后使用递归cte获取每个组id、状态的第一行rid=1,然后递归获取下一行并比较开始/结束日期 ;WITH cte_r(id,[Status],StartDate,EndDate,rid) AS ( SELECT id,[Status],StartDa

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

这就是我所拥有的:

这就是我想看到的:


请尝试以下查询。首先按StartDate对数据进行排序并生成序列rid。然后使用递归cte获取每个组id、状态的第一行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 ;

这是一个典型的缺口和孤岛问题。您希望聚合具有相同Id和状态的连续记录组

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

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、Id和状态对两个不同分区上的记录进行排序来工作。排名之间的差异为您提供了每条记录所属的组。您可以独立运行子查询以查看它返回的内容并理解其逻辑

:


搜索缺口和岛屿。你尝试过什么?如何问好问题。。。多补充一点你的问题会很好,但是如果你想改进你的问题,那么你可以很快尝试使用group By创建一个组,用文本数据替换图像。为了获得额外的积分,请使用DDL/DML语句来构建人们可以用于测试的临时表。这就是我要找的。 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