T-SQL - 聚合(MIN/MAX 日期)考虑时间顺序 - SQL Server 2012

T-SQL - Aggregate (MIN/MAX date) considering chronological sequence - SQL Server 2012

我无法想象如何使用 t-sql.

解决我的问题

我需要以下 table 中的最小和最大日期。

ValidFrom ValidTo Num ID Number
2019-06-01 2019-12-31 100 01234567
2020-01-01 2020-03-31 100 01234567
2020-04-01 2020-12-31 100 01234567
2021-01-01 2021-01-31 100 01234567
2021-02-01 2021-03-31 50 01234567
2021-04-01 2021-09-30 50 01234567
2021-10-01 2021-12-31 50 01234567
2022-01-01 2022-04-30 100 01234567

查询的预期结果:

ValidFrom ValidTo Num ID Number
2019-06-01 2021-01-31 100 01234567
2021-02-01 2021-12-31 50 01234567
2022-01-01 2022-04-30 100 01234567

根据2可以计算出排名ROW_NUMBER
一旦有了排名,就很容易汇总了。

-- rank via ascending row_number + descending row_number
SELECT
  MIN(ValidFrom) AS ValidFrom
, MAX(ValidTo) AS ValidTo
, Num
, [ID Number]
-- , Rnk
FROM
(
    SELECT *
    , Rnk = ROW_NUMBER() OVER (PARTITION BY [ID Number] ORDER BY ValidFrom ASC, ValidTo ASC)
          + ROW_NUMBER() OVER (PARTITION BY [ID Number], Num ORDER BY ValidFrom DESC, ValidTo DESC)
    FROM your_table
) q
GROUP BY [ID Number], Num, Rnk
ORDER BY [ID Number], MIN(ValidFrom)
ValidFrom ValidTo Num ID Number
2019-06-01 2021-01-31 100 1234567
2021-02-01 2021-12-31 50 1234567
2022-01-01 2022-04-30 100 1234567

第二种方法

-- rank via summing flag on change
SELECT
  MIN(ValidFrom) AS ValidFrom
, MAX(ValidTo) AS ValidTo
, Num
, [ID Number]
, Rnk
FROM
(
  SELECT *
  , Rnk = SUM(flag) OVER (PARTITION BY [ID Number] ORDER BY ValidFrom, ValidTo)
  FROM
  (
    SELECT *
    , flag = IIF(Num = LAG(Num) OVER (PARTITION BY [ID Number] ORDER BY ValidFrom, ValidTo), 0, 1)
    FROM your_table
  ) q1
) q2
GROUP BY [ID Number], Num, Rnk
ORDER BY [ID Number], MIN(ValidFrom)

演示 db<>fiddle here