Sql 递归CTE-合并开始和结束日期

Sql 递归CTE-合并开始和结束日期,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有下表: row_num customer_status effective_from_datetime ------- ------------------ ----------------------- 1 Active 2011-01-01 2 Active 2011-01-02 3 Active 2011-01-03 4 Suspended 2

我有下表:

row_num customer_status    effective_from_datetime
------- ------------------ -----------------------
1       Active             2011-01-01
2       Active             2011-01-02
3       Active             2011-01-03
4       Suspended          2011-01-04
5       Suspended          2011-01-05
6       Active             2011-01-06
我试图实现以下结果,即具有相同状态的连续行合并为具有有效起始日期和截止日期范围的一行:

customer_status effective_from_datetime effective_to_datetime
--------------- ----------------------- ---------------------
Active          2011-01-01              2011-01-04
Suspended       2011-01-04              2011-01-06
Active          2011-01-06              NULL
我可以得到一个递归CTE,根据下一行输出正确的有效日期时间,但合并范围时遇到困难

生成示例数据的代码:

CREATE TABLE #temp
(
row_num INT IDENTITY(1,1),
customer_status VARCHAR(10),
effective_from_datetime DATE
)

INSERT INTO #temp
VALUES 
('Active','2011-01-01')
,('Active','2011-01-02')
,('Active','2011-01-03')
,('Suspended','2011-01-04')
,('Suspended','2011-01-05')
,('Active','2011-01-06')

编辑根据注释更新SQL

WITH
  group_assigned_data AS
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY customer_status ORDER BY effective_from_date) AS status_sequence_id,
    ROW_NUMBER() OVER (                             ORDER BY effective_from_date) AS sequence_id,
    customer_status,
    effective_from_date
  FROM
    your_table
)
,
  grouped_data AS
(
  SELECT
    customer_status,
    MIN(effective_from_date)   AS min_effective_from_date,
    MAX(effective_from_date)   AS max_effective_from_date
  FROM
    group_assigned_data
  GROUP BY
    customer_status,
    sequence_id - status_sequence_id
)
SELECT
  [current].customer_status,
  [current].min_effective_from_date       AS effective_from,
  [next].min_effective_from_date          AS effective_to
FROM
  grouped_data   AS [current]
LEFT JOIN
  grouped_data   AS [next]
    ON [current].max_effective_from_date = [next].min_effective_from_date + 1
ORDER BY
  [current].min_effective_from_date
这不是递归的,但这可能是一件好事


它不会处理数据中的缺口。为了解决这个问题,您可以创建一个包含每个相关日期的日历表,并在该日历表上加入以“未知”状态填充缺少的日期,然后针对该日历表运行查询。(事实上,您可以使用上述CTE使用的CTE进行操作)

目前……
-如果缺少第2行,则不会更改结果
-如果缺少第3行,则第一行的结束日期将更改

通过准备数据或其他方法可以确定不同的行为。不过,我们需要了解您需要的业务逻辑



如果任何一个日期可以有多个状态条目,则需要定义希望它遵循的逻辑。目前,行为尚未定义,但您可以纠正这一点,只需将
customer\u status
添加到
ORDER BY
行号()的部分即可。

哦,我不想使用游标或循环,因为计划是在视图中使用此逻辑。如果您没有日期条目怎么办?这应该被视为序列中的一个间隙吗?e、 g.假设
('Active','2011-01-02')
行不存在?我看到的一个问题(我认为这使解决方案完全不同)-有效的to datetime应该等于下一行的有效from datetime。@shakedown7-这就是我提到的“差距”情况。如果存在间隙,最简单的解决方案是将其保留在日历表上以填补间隙。这将导致出现三种类型的组,其中一种与您的差距有关,您可以给出一个名称或选择在之后过滤掉。感谢Dems,我认为这与“差距”情况不同。对于该分组,有效\u到\u日期时间不应为最大值(有效\u自\u日期时间),而应为下一组的最小值(有效\u自\u日期时间)。即,“活动”行的有效日期时间应为2011-01-04,这是“暂停”行的开始日期(与2011-01-03相反)。@shakedown7-哦,我明白了。你需要把结果留给他们自己。我将添加一个示例。