【问题标题】:Admission/discharge joined into single episode of care入院/出院加入单期护理
【发布时间】:2020-06-07 20:01:07
【问题描述】:

我的问题与这里描述的问题类似:Check if date falls between previous row start date and end date

但是,在我的数据中,可能有多个事件重叠,我也想返回不重叠的行。数据:

PatientID   Facility  Encounter #    FromDate      ToDate
-------------------------------------------------------------
    5          A         22         2017/02/14    2017/02/19
    5          B         55         2017/02/19    2017/04/15
    5          C         66         2017/04/15    2017/08/19
    7          A        198         2018/06/27    2018/08/13
    8          D        222         2019/07/18    2019/12/06
    8          A       2305         2019/12/06    2020/01/07
    8          C       2223         2020/03/31    2020/05/17
    9          C      12312         2018/01/12    2020/02/04

在上面的示例中,客户 5 和 8 在他们的出院日期(从以前的遭遇)入院。每当入院日期与前一行的出院日期相同时(按时间顺序),我需要将日期加入一次护理(例如,对于患者 5,它是遇到 22,55 和 66;对于患者 8,它是遇到 222、2305)。我还希望输出不是这种情况的情况(患者 ID 7 和 9 并遇到患者 8 的 2223)

期望的输出:

PatientID   FromDate      ToDate
-----------------------------------
    5      2017/02/14    2017/08/19
    7      2018/06/27    2018/08/13
    8      2019/07/18    2020/01/07
    8      2020/03/31    2020/05/17
    9      2018/01/12    2020/02/04

我正在使用 SQL Server 2016。非常感谢您的帮助!

【问题讨论】:

  • 将来,为 SQL Fiddle 提供已经设置好的表和数据。此外,请提供您迄今为止所做的尝试。
  • 好点!对于不包括 SQL Fiddle 或我尝试过的代码,我深表歉意。在发布之前,我尝试过使用类似于下面的 CROSS APPLY,但在接下来的步骤中被卡住了。SELECT Main.PatientID ,Main.FromDate ,Main.ToDate ,Main.Facility ,Main.[Encounter #] ,a.ToDate ,lag(a.ToDate) OVER (partition by Main.PatientID ORDER BY Main.FromDate) FROM Encounter Main cross APPLY (SELECT TOP 1 ToDate FROM Encounter NextAdm WHERE NextAdm.PatientID=Main.PatientID AND Main.ToDate=NextAdm.FromDate ORDER BY ToDate DESC ) a

标签: sql-server date join


【解决方案1】:

您可以使用recursive CTE 将“先前”遭遇与“后续”遭遇加入。第一步是确定从哪些记录开始——在这种情况下,我们要查找给定患者的记录,其FromDate 没有匹配的ToDate。我们通过左外连接和过滤“上一个”记录中的null 值来做到这一点:

select
  subs.PatientId
  , subs.FromDate
  , subs.ToDate
from
  Encounter subs
  left outer join Encounter prev
   on subs.PatientId = prev.PatientId
      and subs.FromDate = prev.ToDate
where
  -- we want encounters that aren't preceded
  -- by another encounter
  prev.PatientId is null

接下来,我们希望通过先前的 FromDate 等于后续的 ToDate 将结果与给定患者的 Encounter 记录递归连接,以便我们可以扩展结果的 ToDate。我们通过在前面提到的标准上将结果(我们将称为 CrossFacilityEncounter 的 CTE)与 Encounter 表内部连接来做到这一点:

select
  prev.PatientId
  , prev.FromDate
  , subs.ToDate
from
  -- this CTE is the "previous" encounter
  CrossFacilityEncounter prev
  inner join Encounter subs
    on prev.PatientId = subs.PatientId
       and prev.ToDate = subs.FromDate

将所有内容放在递归 CTE 中,您会得到:

with CrossFacilityEncounter
(
  PatientId
  , FromDate
  , ToDate
)
as
(
  -- start with first encounter in a sequence
  -- for a given patient
  select
    subs.PatientId
    , subs.FromDate
    , subs.ToDate
  from
    Encounter subs
    left outer join Encounter prev
     on subs.PatientId = prev.PatientId
        and subs.FromDate = prev.ToDate
  where
    -- we want encounters that aren't preceded
    -- by another encounter
    prev.PatientId is null
  UNION ALL
  select
    prev.PatientId
    , prev.FromDate
    , subs.ToDate
  from
    -- this CTE is the "previous" encounter
    CrossFacilityEncounter prev
    inner join Encounter subs
      on prev.PatientId = subs.PatientId
         and prev.ToDate = subs.FromDate
)

结果将为我们提供PatientId,每个序列的初始FromDate,以及ToDate/FromDate,即序列的一个片段(相遇)的结束和下一个序列的开始(如果适用) .有了这个我们可以做很多事情,但你只是对序列的开始和结束日期感兴趣,所以只需为每个 {PatientId, FromDate} 元组返回 FromDate 的最大值:

select
  PatientId
  , FromDate
  , MAX(ToDate)
from
    CrossFacilityEncounter
group by
  PatientId
  , FromDate
order by
  PatientId

SQL Fiddle

【讨论】:

  • 非常感谢!我刚刚尝试过为我自己的数据调整代码,但由于某种原因,代码已经在 50k 记录的表上运行了 90 分钟(并且仍在运行)。这可能是我的问题。将保持联系。
猜你喜欢
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多