如何识别特定时间范围内发生的行?
How to identify rows that occur within a specific time frame?
我有一个 table,其中包含患者的医院就诊信息。我试图标记上次访问后 90 天内发生的访问。但是,需要注意的是,一旦访问被标记为重叠访问,则不应使用该访问来评估与另一次访问的重叠。让我用一个例子来解释。
Table
visitID patientid visit_date
1 23 1/12/2018
2 23 1/30/2018
3 23 4/20/2018
4 23 5/02/2018
在上面的例子中,患者进行了 4 次就诊。访问 2 在访问 1 的 90 天内,因此访问 2 应标记为重叠。一旦访问 2 被标记,该行不应用于任何未来访问的重叠识别分析。从概念上讲,这就像删除访问 2 并重新开始分析。
中间阶段(访问 2 被删除,分析再次开始)
visitID patientid visit_date
1 23 1/12/2018
3 23 4/20/2018
4 23 5/02/2018
因此,即使访问 3 与访问 2 重叠,由于访问 2 已从分析中删除,访问 3 也不会被标记为上一次访问(访问 1)距 90 天更远。最后,应标记第 4 次访问,因为它与未标记的访问重叠。
预期产出
visitID patientid visit_date flag
1 23 1/12/2018 0
2 23 1/30/2018 1
3 23 4/20/2018 0
4 23 5/02/2018 1
我的解谜尝试:
WITH overlaps AS
(SELECT DISTINCT T2.visit
FROM visits_table AS T1
INNER JOIN visits_table AS T2
ON T1.visit != T2.visit
AND T2.visit_date BETWEEN T1.visit_date AND DATEADD(DAY, 89, T1.visit_date))
SELECT T3.visit, T3.patientid, T3.visit_date,
CASE WHEN EXISTS (SELECT 1 FROM overlaps
WHERE overlaps.visit = T3.visit)
THEN 1
ELSE 0
END flag
FROM visits_table T3
我的代码所做的是检查每一行,而不管它是否应该用于分析。我不知道如何让它动态化,以便它忽略应该忽略的行。
数据集:
create table visits_table (visit int,patientid int,visit_date date);
INSERT INTO visits_table (visit, patientid, visit_date) VALUES (1,23,'1/12/2018')
INSERT INTO visits_table (visit, patientid, visit_date) VALUES (2,23,'1/30/2018')
INSERT INTO visits_table (visit, patientid, visit_date) VALUES (3,23,'4/20/2018')
INSERT INTO visits_table (visit, patientid, visit_date) VALUES (4,23,'5/02/2018')
我相信您必须使用递归 CTE 来执行此操作:
with vt as (
select vt.*, row_number() over (partition by patientid order by visit_date) as seqnum
from visits_table vt
),
cte as (
select vt.visit, vt.patientid, vt.visit_date, vt.visit_date as first_visit_date, seqnum
from vt
where seqnum = 1
union all
select vt.visit, vt.patientid, vt.visit_date,
(case when vt.visit_date > dateadd(day, 90, cte.first_visit_date) then vt.visit_date else cte.first_visit_date end),
vt.seqnum
from cte join
vt
on vt.seqnum = cte.seqnum + 1 and vt.patientid = cte.patientid
)
select cte.visit, cte.patientid, cte.visit_date,
(case when first_visit_date = visit_date then 0 else 1 end) as flag
from cte
order by cte.patientid, cte.visit_date;
Here 是一个 db<>fiddle.
我有一个 table,其中包含患者的医院就诊信息。我试图标记上次访问后 90 天内发生的访问。但是,需要注意的是,一旦访问被标记为重叠访问,则不应使用该访问来评估与另一次访问的重叠。让我用一个例子来解释。
Table
visitID patientid visit_date
1 23 1/12/2018
2 23 1/30/2018
3 23 4/20/2018
4 23 5/02/2018
在上面的例子中,患者进行了 4 次就诊。访问 2 在访问 1 的 90 天内,因此访问 2 应标记为重叠。一旦访问 2 被标记,该行不应用于任何未来访问的重叠识别分析。从概念上讲,这就像删除访问 2 并重新开始分析。
中间阶段(访问 2 被删除,分析再次开始)
visitID patientid visit_date
1 23 1/12/2018
3 23 4/20/2018
4 23 5/02/2018
因此,即使访问 3 与访问 2 重叠,由于访问 2 已从分析中删除,访问 3 也不会被标记为上一次访问(访问 1)距 90 天更远。最后,应标记第 4 次访问,因为它与未标记的访问重叠。
预期产出
visitID patientid visit_date flag
1 23 1/12/2018 0
2 23 1/30/2018 1
3 23 4/20/2018 0
4 23 5/02/2018 1
我的解谜尝试:
WITH overlaps AS
(SELECT DISTINCT T2.visit
FROM visits_table AS T1
INNER JOIN visits_table AS T2
ON T1.visit != T2.visit
AND T2.visit_date BETWEEN T1.visit_date AND DATEADD(DAY, 89, T1.visit_date))
SELECT T3.visit, T3.patientid, T3.visit_date,
CASE WHEN EXISTS (SELECT 1 FROM overlaps
WHERE overlaps.visit = T3.visit)
THEN 1
ELSE 0
END flag
FROM visits_table T3
我的代码所做的是检查每一行,而不管它是否应该用于分析。我不知道如何让它动态化,以便它忽略应该忽略的行。
数据集:
create table visits_table (visit int,patientid int,visit_date date);
INSERT INTO visits_table (visit, patientid, visit_date) VALUES (1,23,'1/12/2018')
INSERT INTO visits_table (visit, patientid, visit_date) VALUES (2,23,'1/30/2018')
INSERT INTO visits_table (visit, patientid, visit_date) VALUES (3,23,'4/20/2018')
INSERT INTO visits_table (visit, patientid, visit_date) VALUES (4,23,'5/02/2018')
我相信您必须使用递归 CTE 来执行此操作:
with vt as (
select vt.*, row_number() over (partition by patientid order by visit_date) as seqnum
from visits_table vt
),
cte as (
select vt.visit, vt.patientid, vt.visit_date, vt.visit_date as first_visit_date, seqnum
from vt
where seqnum = 1
union all
select vt.visit, vt.patientid, vt.visit_date,
(case when vt.visit_date > dateadd(day, 90, cte.first_visit_date) then vt.visit_date else cte.first_visit_date end),
vt.seqnum
from cte join
vt
on vt.seqnum = cte.seqnum + 1 and vt.patientid = cte.patientid
)
select cte.visit, cte.patientid, cte.visit_date,
(case when first_visit_date = visit_date then 0 else 1 end) as flag
from cte
order by cte.patientid, cte.visit_date;
Here 是一个 db<>fiddle.