sha*_*wn7 6 sql t-sql sql-server
我有下表:
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
Run Code Online (Sandbox Code Playgroud)
我正在尝试获得以下结果,即具有相同状态的连续行合并为一行,并具有有效的起始和日期范围:
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
Run Code Online (Sandbox Code Playgroud)
我可以得到一个递归CTE,根据下一行输出正确的effective_to_datetime,但是在合并范围时遇到问题.
用于生成样本数据的代码:
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')
Run Code Online (Sandbox Code Playgroud)
编辑 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
Run Code Online (Sandbox Code Playgroud)
这不是递归的,但这可能是一件好事.
它不处理数据中的差距.为了解决这个问题,您可以创建一个包含每个相关日期的日历表,然后加入该日历表以填充"未知"状态的缺失日期,然后针对该日期运行查询.(事实上,你可以把它作为上面CTE使用的CTE).
目前...
- 如果第2行丢失,它不会改变结果
- 如果第3行丢失,第一行的end_date将改变
可以通过准备数据或其他方法来确定不同的行为.我们需要知道您需要的业务逻辑.
如果任何一个日期可以有多个状态条目,则需要定义要遵循的逻辑.目前行为是未定义的,但您可以像添加customer_status到ORDER BYROW_NUMBER()的部分一样纠正它.