我有以下格式的数据,其中包含几个状态代码及其日期。有问题的代码是 3 和 8。我需要找到
STcode=3/8
的开始日期并将其用作 STDATE
,如果 STCODE
更改为 3/8 以外的其他时间,那么它将成为我的 ENDDATE
在以下示例中,ID 101 在
STCODE=3
首次进入 10/21/2022
,并在 6
将其状态更改为 10/26/2022
。再次在10/26/2022
,它位于STCODE=3
,更改日期为10/27/2022
。我需要在输出中将它们作为两个单独的记录
ID STCODE DATE
101 3 10/21/2022
101 3 10/22/2022
101 3 10/23/2022
101 6 10/25/2022
101 3 10/26/2022
101 7 10/27/2022
102 8 10/25/2022
102 5 10/26/2022
想要
ID STDATE ENDDATE
101 10/21/2022 10/25/2022
101 10/26/2022 10/27/2022
102 10/25/2022 10/26/2022
我尝试了类似的方法,但没有产生任何预期的结果
WITH STS AS (
SELECT
ID,
STCODE,
DATE,
ROW_NUMBER() OVER (ORDER BY DATE) AS rn,
ROW_NUMBER() OVER (PARTITION BY STCODE ORDER BY DATE) AS str_rn
FROM
MyTable
)
SELECT
ID,
MIN(DATE) AS STDATE,
MAX(DATE) AS ENDDATE
FROM STS
WHERE
STCODE in (3,8)
GROUP BY ID
您需要确保这可以处理所有潜在的情况,但它适用于示例数据,并且是相当标准方法的要点。
基本原理 - 使用 Lead() 获取下一个状态代码和关联日期。然后过滤掉状态码处于非过期触发状态的记录。完成此操作后,您将只剩下每个状态序列中具有适当结束日期的第一条记录。
CREATE VOLATILE TABLE SampleData (
ID INTEGER,
STCODE INTEGER,
event_date DATE
) ON COMMIT PRESERVE ROWS;
-- Inserts
INSERT INTO SampleData (ID, STCODE, event_date) VALUES (101, 3, DATE '2022-10-21');
INSERT INTO SampleData (ID, STCODE, event_date) VALUES (101, 3, DATE '2022-10-22');
INSERT INTO SampleData (ID, STCODE, event_date) VALUES (101, 3, DATE '2022-10-23');
INSERT INTO SampleData (ID, STCODE, event_date) VALUES (101, 6, DATE '2022-10-25');
INSERT INTO SampleData (ID, STCODE, event_date) VALUES (101, 3, DATE '2022-10-26');
INSERT INTO SampleData (ID, STCODE, event_date) VALUES (101, 7, DATE '2022-10-27');
INSERT INTO SampleData (ID, STCODE, event_date) VALUES (102, 8, DATE '2022-10-25');
INSERT INTO SampleData (ID, STCODE, event_date) VALUES (102, 5, DATE '2022-10-26');
with next_stcodes as (
select sd.*,
lead(event_date) over ( partition by id order by event_date) as end_date,
lead(stcode) over ( partition by id order by event_date) as next_stcode
from SampleData sd)
select id,
event_date,
coalesce(end_date, DATE '9999-12-31') as end_date
from next_stcodes
where stcode in (3,8)
and (
next_stcode not in (3,8)
or next_stcode is null
);