【问题标题】:How to remove overlapping rows based on date and keep most recent in sql?如何根据日期删除重叠行并在 sql 中保持最新?
【发布时间】:2018-07-03 04:28:30
【问题描述】:

我需要找到每位患者的所有 episode_id。但是,如果在前一集的 90 天内出现重叠集,那么我只想保留最近的集。

例如patient_num 3242下面有3集:90天内第二集与第一集重叠,90天内第三集与第二集重叠,这种情况我只需要保留第三集.

CREATE TABLE table1 (episode_id nvarchar(max), patient_num nvarchar(max), admit_date date,  discharge_date date)

INSERT INTO table1 (episode_id, patient_num , admit_date ,  discharge_date ) VALUES 
('1','5743','1/1/2016','1/5/2016'),
('2','5743','4/26/2016','4/29/2016'),
('3','5743','5/26/2016','5/28/2016'),
('4','5743','9/21/2016','9/28/2016'),
('5','8859','4/27/2016','5/5/2016'),
('6','3242','4/28/2016','4/29/2016'),
('7','3242','11/21/2016','11/23/2016'),
('8','3242','11/24/2016','11/29/2016'),
('9','3242','12/12/2016','12/29/2016')

初始表(table1)

episode_id   patient_num  admit_date   discharge_date
1            5743         2016-01-01   2016-01-05 
2            5743         2016-04-26   2016-04-29
3            5743         2016-05-26   2016-05-28
4            5743         2016-09-21   2016-09-28
5            8859         2016-04-27   2016-05-05
6            3242         2016-04-28   2016-04-29
7            3242         2016-11-21   2016-11-23
8            3242         2016-11-24   2016-11-29
9            3242         2016-12-12   2016-12-29

预期结果

episode_id   patient_num  admit_date   discharge_date
1            5743         2016-01-01   2016-01-05 
3            5743         2016-05-26   2016-05-28
4            5743         2016-09-21   2016-09-28
5            8859         2016-04-27   2016-05-05
6            3242         2016-04-28   2016-04-29
9            3242         2016-12-12   2016-12-29

我的尝试:

SELECT *
FROM table1 AS a
WHERE EXISTS
(
    SELECT *
    FROM table1 AS b
    WHERE      a.episode_id != b.episode_id
               AND a.patient_num= b.patient_num
               AND a.admit_date BETWEEN b.discharge_date AND DATEADD(DAY, 90, b.discharge_date ))

我的脚本中的错误是,对于患者编号 3242,我得到了第 8 集和第 9 集,而我只想要第 9 集。我假设这个错误的原因是我正在单独比较每一行而不是的作为一个组,但我无法分组。此外,此脚本未显示不存在重叠的实例,例如 episode_id 1、4、5、6。对此方法有何建议?

【问题讨论】:

  • 给我们脚本来生成上面的表格
  • 我添加了一个脚本来生成表格
  • 我从数据中看到这是不正确的:他的第二集在 90 天内与第一集重叠
  • 第一集和第二集相隔112天。
  • 恕我直言,我们需要选择所有 NON_Overlapped 行。然后从其他人中创建 OverlapRanges 并从每个 OverlapRange 中选择 TOP 1。例如请克隆第 7、8、9 集并将它们的年份更改为 2017 年。我尚未解决的部分是创建 OverlapRange。我正在使用 Celko-s 对 Smarties 的 SQL 中的 Overlap 定义,这与 BETWEEN 略有不同,其中包括端点,而 Overlap 没有。

标签: sql sql-server overlapping


【解决方案1】:

我在这里删除了光标解决方案,因为它性能低 不使用 Cursor 的解决方案是:

WITH ExcludedIds AS (
SELECT DISTINCT T2.episode_id 
FROM table1  AS T 
INNER JOIN table1 AS T2 ON T.episode_id != T2.episode_id
               AND T.patient_num = T2.patient_num
               AND T2.discharge_date BETWEEN DATEADD(DAY, -90, T.admit_date ) AND  T.discharge_date)

SELECT T.episode_id, T.patient_num, T.admit_date, T.discharge_date 
FROM table1 AS T 
WHERE T.episode_id NOT IN (SELECT ExcludedIds.episode_id FROM ExcludedIds)

认为理解这个解决方案有点困难。

【讨论】:

  • 这可以使用基于集合的逻辑来解决。光标绝对不是正确的方法。
  • 你怎么知道游标效率不高。您是否曾经将子查询性能与 fast_forward 只读游标进行比较。总是有一个权衡。它还取决于表有多少条记录。
  • 。 .自 1989 年以来,我一直在使用关系数据库。是的,在过去,我有时会比较性能。我也了解它们的工作原理。
  • 这太棒了!我比游标更了解 CTE,所以加 1!此外,您的 CTE 答案大约需要 10 分钟,而光标大约需要 2 小时。
  • 我很高兴它有帮助。我认为@GordonLinoff 应该对他的评论而不是他的解决方案进行投票。
【解决方案2】:

我认为not exists 可以满足您的需求:

SELECT a.*
FROM table1 a
WHERE NOT EXISTS (SELECT 1
                  FROM table1 b
                  WHERE a.episode_id <> b.episode_id AND
                        a.patient_num = b.patient_num AND
                        b.admin_date < a.discharge_date AND
                        b.discharge_date >= DATEADD(DAY, -90, a.discharge_date)
                 );

【讨论】:

  • 您的查询返回所有 9 条记录。编写一个好的查询的第一件事是它必须是正确的。接下来是效率。
  • 我确实对您的代码投了反对票,而不是您,这是因为您的答案是错误的。为什么你认为它很粗鲁?请不要认为它是个人的。我认为投反对票表明其他人不专注于答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 1970-01-01
  • 1970-01-01
  • 2015-03-29
  • 2021-09-21
相关资源
最近更新 更多