我有一张表,其中包含患者的医院就诊情况。我正在尝试标记一次访问的 begin_date
与之前的访问的 end_date
+ 90 天重叠的访问。然而,需要注意的是,一旦一次访问被标记为重叠访问,该访问就不应用于评估与另一次访问的重叠。让我用一个例子来解释一下。
表格
visitID patientid begin_date end_date
1 23 1/12/2018 1/14/2018
2 23 1/30/2018 2/14/2018
3 23 4/20/2018 4/22/2018
4 23 5/02/2018 5/03/2018
5 23 7/23/2018 7/28/2018
在上面的示例中,患者就诊了 5 次。访问 2 的 begin_date
位于访问 1 的 end_date
+ 90 天范围内,因此应标记访问 2。一旦标记了访问 2,该行就不应用于任何 future 访问的分析。从概念上讲,这就像删除访问 2 并重新开始分析。
中期阶段(访问 2 被删除,分析再次开始)
visitID patientid begin_date end_date
1 23 1/12/2018 1/14/2018
3 23 4/20/2018 4/22/2018
4 23 5/02/2018 5/03/2018
5 23 7/23/2018 7/28/2018
因此,即使访问 3 与访问 2 重叠,由于访问 2 已被删除,访问 3 也不会被标记为上次访问(现在访问 1)已超过 end_date
+ 90 天从访问 3 的 begin_date
开始。然后,应标记访问 4,因为它与未标记的访问(访问 3)重叠。因此,由于访问 4 已被标记,因此访问 5 将被删除,因为它的 begin_date
位于访问 3 的 end_date
+ 90 天范围内。
预期输出
visitID patientid begin_date end_date flag
1 23 1/12/2018 1/14/2018 0
2 23 1/30/2018 2/14/2018 1
3 23 4/20/2018 4/22/2018 0
4 23 5/02/2018 5/03/2018 1
5 23 7/23/2018 7/28/2018 1
@gordonlinoff回答了一个非常相似的问题here ,但我在使用递归 CTE 时遇到了问题。这些问题之间的区别在于,该问题需要引用另一列 (end_date
),而不是单个日期列。递归 CTE 对我来说仍然是一个新概念,但我希望这将有助于巩固这个概念。
我尝试解决这个难题(小 pig 从@gordonlinoff退缩):
with vt as (
select vt.*, row_number() over (partition by patientid order by begin_date) as seqnum
from visits_table vt
),
cte as (
select vt.visit, vt.patientid, vt.begin_date, vt.end_date, vt.begin_date as first_begin_date, seqnum
from vt
where seqnum = 1
union all
select vt.visit, vt.patientid, vt.begin_date, vt.end_date,
(case when vt.begin_date > dateadd(day, 90, cte.end_date) then vt.begin_date else cte.end_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.begin_date, cte.end_date,
(case when first_begin_date = begin_date then 0 else 1 end) as flag
from cte
order by cte.patientid, cte.begin_date;
我的编辑不正确地引用了基于结果的结束日期。但是,我找不到 begin_date
和 end_date
之间的比较应该在哪里。
数据集:
create table visits_table (visit int,patientid int,begin_date date, end_date date);
INSERT INTO visits_table (visit, patientid, begin_date, end_date) VALUES (1,23,'1/12/2018','1/14/2018')
INSERT INTO visits_table (visit, patientid, begin_date, end_date) VALUES (2,23,'1/30/2018','2/14/2018')
INSERT INTO visits_table (visit, patientid, begin_date, end_date) VALUES (3,23,'4/20/2018','4/22/2018')
INSERT INTO visits_table (visit, patientid, begin_date, end_date) VALUES (4,23,'5/02/2018','5/03/2018')
最佳答案
我调整了您的样本数据,使访问 5 位于访问 3 的结束日期 + 90 天的范围内。访问 3 结束日期为 2018-04-22
。如果我们加上 90 天,那就是 2018-07-21
。您问题中的示例数据的访问起始日期为 2018-07-23
,与 2018-07-21
不重叠。因此,我将其调整为 2018-07-20
以使这些日期重叠。
create table visits_table (visit int,patientid int,begin_date date, end_date date);
INSERT INTO visits_table (visit, patientid, begin_date, end_date) VALUES
(1,23,'2018-01-12','2018-01-14'),
(2,23,'2018-01-30','2018-02-14'),
(3,23,'2018-04-20','2018-04-22'),
(4,23,'2018-05-02','2018-05-03'),
(5,23,'2018-07-20','2018-07-28');
您的查询非常接近,您只需计算“上一个”间隔的开始日期和结束日期(first_begin_date,first_end_date)
。
如果“当前”间隔与“上一个”间隔重叠,则将“上一个”间隔移入当前行。
取消注释下面查询中的行以查看所有中间值。
with
vt
as
(
select vt.*, row_number() over (partition by patientid order by begin_date) as seqnum
from visits_table vt
)
,cte
as
(
select
vt.visit
,vt.patientid
,vt.begin_date as first_begin_date
,vt.end_date as first_end_date
,vt.begin_date
,vt.end_date
,seqnum
from vt
where seqnum = 1
union all
select
vt.visit
,vt.patientid
,case when vt.begin_date <= dateadd(day, 90, cte.first_end_date)
then cte.first_begin_date -- they overlap, keep the previous interval
else vt.begin_date
end as first_begin_date
,case when vt.begin_date <= dateadd(day, 90, cte.first_end_date)
then cte.first_end_date -- they overlap, keep the previous interval
else vt.end_date
end as first_end_date
,vt.begin_date
,vt.end_date
,vt.seqnum
from
cte
inner join vt
on vt.seqnum = cte.seqnum + 1
and vt.patientid = cte.patientid
)
select
cte.visit
,cte.patientid
,cte.begin_date
,cte.end_date
,case when first_begin_date = begin_date
then 0 else 1
end as flag
-- ,DATEADD(day, 90, cte.end_date) AS enddd
-- ,*
from cte
order by cte.patientid, cte.begin_date;
结果
+-------+-----------+------------+------------+------+
| visit | patientid | begin_date | end_date | flag |
+-------+-----------+------------+------------+------+
| 1 | 23 | 2018-01-12 | 2018-01-14 | 0 |
| 2 | 23 | 2018-01-30 | 2018-02-14 | 1 |
| 3 | 23 | 2018-04-20 | 2018-04-22 | 0 |
| 4 | 23 | 2018-05-02 | 2018-05-03 | 1 |
| 5 | 23 | 2018-07-20 | 2018-07-28 | 1 |
+-------+-----------+------------+------------+------+
关于sql - 如何正确应用递归CTE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56120485/