【问题标题】:Drop rows identified within moving time window删除在移动时间窗口内识别的行
【发布时间】:2014-07-30 16:23:48
【问题描述】:

我有一个住院治疗数据集(“咒语”) - 每个咒语 1 行。我想删除一个接一个一周内记录的任何咒语(可能有多个) - 理由是它们可能是相同根本原因的症状。这是一些播放数据:

create table hif_user.rzb_recurse_src (
patid integer not null,
eventdate integer not null,
type smallint not null
);

insert into hif_user.rzb_recurse_src values (1,1,1);
insert into hif_user.rzb_recurse_src values (1,3,2);
insert into hif_user.rzb_recurse_src values (1,5,2);
insert into hif_user.rzb_recurse_src values (1,9,2);
insert into hif_user.rzb_recurse_src values (1,14,2);
insert into hif_user.rzb_recurse_src values (2,1,1);
insert into hif_user.rzb_recurse_src values (2,5,1);
insert into hif_user.rzb_recurse_src values (2,19,2);

只有类型 2 的咒语 - 在任何其他咒语之后的一周内 - 才能被丢弃。类型 1 法术将保留。

对于患者 1,应保留日期 1 和 9。对于患者 2,应保留所有行。

问题出在患者 1 上。由于接近于拼写日期 5,拼写日期 9 被确定为丢弃;但是,由于拼写日期 5 接近于拼写日期 1,因此应删除拼写日期 9,因此应保留拼写日期 9...

所以,这似乎是一个递归问题。但是,我以前没有在 SQL 中使用过递归编程,我正在努力想象如何做到这一点。任何人都可以帮忙吗?我应该补充一点,我使用的 Teradata 比大多数递归 SQL 具有更多限制(我相信只允许 UNION ALL 集)。

【问题讨论】:

  • 您的eventdate 是以天为单位存储的吗?
  • 是的,应该说。

标签: sql teradata recursive-query


【解决方案1】:

这是一种游标逻辑,如果符合您的规则,请逐行检查,因此递归是解决问题的最简单(也许是唯一)方法。

要获得不错的性能,您需要一个易失性表来促进这种逐行处理:

CREATE VOLATILE TABLE vt (patid, eventdate, exac_type, rn, startdate) AS
(
SELECT r.*
   ,ROW_NUMBER() -- needed to facilitate the join
    OVER (PARTITION BY patid ORDER BY eventdate) AS rn
FROM hif_user.rzb_recurse_src AS r
) WITH DATA ON COMMIT PRESERVE ROWS;

WITH RECURSIVE cte (patid, eventdate, exac_type, rn, startdate) AS
 (
   SELECT vt.*
     ,eventdate AS startdate 
   FROM vt
   WHERE rn = 1 -- start with the first row

   UNION ALL

   SELECT vt.*
     -- check if type = 1 or more than 7 days from the last eventdate
     ,CASE WHEN vt.eventdate > cte.startdate + 7  
             OR vt.exac_type = 1
           THEN vt.eventdate   -- new start date
           ELSE cte.startdate  -- keep old date
      END
   FROM vt JOIN cte
     ON vt.patid = cte.patid
    AND vt.rn = cte.rn + 1 -- proceed to next row
 )    
SELECT * 
FROM cte
WHERE eventdate - startdate = 0 -- only new start days
order by patid, eventdate

【讨论】:

  • 太棒了,它是一种享受。奇怪的是,这是我读到的最简单的递归 SQL 示例之一(不是批评!)。再次感谢!
【解决方案2】:

我认为解决这个问题的关键是让第一个日期距当前日期超过 7 天,然后进行递归子查询:

with rrs as (
      select rrs.*,
             (select min(rrs2.eventdate)
              from hif_user.rzb_recurse_src rrs2
              where rrs2.patid = rrs.patid and
                    rrs2.eventdate > rrs.eventdate + 7
             ) as eventdate7
      from hif_user.rzb_recurse_src rrs
     ),
     recursive cte as (
      select patid, min(eventdate) as eventdate, min(eventdate7) as eventdate7
      from hif_user.rzb_recurse_src rrs
      group by patid
      union all
      select cte.patid, cte.eventdate7, rrs.eventdate7
      from cte join
           hif_user.rzb_recurse_src rrs
           on rrs.patid = cte.patid and
              rrs.eventdate = cte.eventdate7
    )
select cte.patid, cte.eventdate
from cte;

如果您想要更多列,请在最后一步加入原始表。

【讨论】:

    猜你喜欢
    • 2018-11-16
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    • 2011-01-13
    • 1970-01-01
    相关资源
    最近更新 更多