【问题标题】:Using CASE statement to only show certain results in a column (also creating duplicates)使用 CASE 语句仅在列中显示某些结果(也创建重复项)
【发布时间】:2020-12-15 17:59:23
【问题描述】:

对不起,如果这没有意义 - 我不知道如何措辞。让我试着解释得更好。

我目前正在处理一个非常基本的查询,用于查看属于诊所的患者的人口统计信息。该查询使用CASE 语句创建了几个新列,这些列可以在 Excel 中过滤,以便用户稍后查看数据。

其中一个CASE 声明围绕患者是否活跃于诊所——他们必须在过去 3 年内被视为活跃。该语句仅查看患者的最后一次就诊日期,计算该日期与今天日期之间的差异,如果该差异小于 3 年,则显示“是”。

但是患者有所谓的标志。当医生访问患者的图表时,会弹出不同的标记,指示患者的服务/治疗逾期、未付账单等。可用标记之一是“非活动患者!”当图表被停用、患者死亡或转移护理等时,由医疗记录部门手动添加。

此查询的目的是显示系统中所有患者的所有人口统计数据,然后有一个字段指示他们是否有“非活动患者!”标志,然后可以与它们是否按照 3 年标准进行比较。所以我有第二个CASE 语句设置为如果患者的图表上附加了该标志,则显示“是”。请注意,我不想看到不活跃的患者,而是所有可用的患者以及这些患者是否有标记。

我的查询有效,尽管一旦我添加了新的CASE 语句来检查非活动标志,它就会减慢速度并运行整整 6 分钟。诚然,系统中有大约 30,000 名患者,其中大多数在他们的图表上附加了许多标志,但这似乎仍然需要很长时间。对于确实有该标志的患者,我也会得到重复的结果,因为我选择了不同的记录,但第一个 CASE 声明为 active-within-3-years 患者不会创建重复。

简而言之,我觉得我不会以最有效的方式来解决这个问题。有人对如何清理这个有任何建议吗?请参阅下面的查询。

SELECT DISTINCT
    d.PatientID
    ,d.PatientName
    ,...[other demographic fields like DOB, gender, race]
    ,a.LastVisitDate
    ,a.NextApptDate
    ,(CASE
        WHEN a.LastVisitDate > DATEADD(yy,-3,GETDATE()) THEN 'YES'
        ELSE ''
     END) AS [Active?]
    ,(CASE
        WHEN d.PatientFlag = 'Inactive Patient!' THEN 'YES'
        ELSE ''
     END) AS [Inactive Flag?]

FROM Demographic d FULL OUTER JOIN Appointment a ON d.PatientID = a.PatientID

重复的结果最终看起来像这样。具有非活动标志的患者会重复其整行人口统计信息,然后一行显示标志指示器,而另一行则不显示。

PatientID    PatientName    ...    LastVisitDate  NextApptDate  Active?    Inactive Flag?
-------------------------------------------------------------------------------------------
1001         John Smith     ...    01/03/2020     NULL          YES
1002         Jane Doe       ...    07/23/2020     12/29/2020    YES        
1002         Jane Doe       ...    07/23/2020     12/29/2020    YES        YES
1003         Bob Brown      ...    NULL           12/21/2020    YES

更新:这是我得到的实际重复结果之一的示例。正如我们所见,该患者的其中一行具有由CASE 创建的非活动指示器,而另一行则没有(因此使它们成为两个唯一行)。该患者最后一次见到是今年,因此按照 3 年的标准,他们仍然活跃,但他们的图表上无疑有非活跃标志,因为他们现在已经去世。该患者在系统中还总共有 35 次过去就诊,显然我的结果中没有得到所有 35 次就诊。这是因为LastVisitDateNextApptDate 是唯一的,并且与PatientID 具有1:1 的关系。

【问题讨论】:

  • 哪个表包含重复项?我假设约会表?一个人可以有很多约会是有道理的。下一个问题:人口统计表与 PatientID 是一对一的还是一对多的。基本上,在我看来,您需要取出 FULL OUTER JOIN ...它确实需要是 INNER JOIN,除非您的数据有一些我不理解的地方。
  • 为什么是FULL JOIN
  • @CodeNovice 我用重复结果的示例更新了问题。当有人拥有非活动标志时,整个患者行都会被复制。上次访问日期和下一个应用日期字段都是唯一的,每个字段都只查看一个日期。
  • @Eric 我正在使用完全联接,因为并非每位患者都有有效的最后一次就诊日期或安排未来的预约,因此之前在这两个字段中具有 NULL 的任何人都被排除在外。
  • 这些是 case 表达式,而不是语句。并且表格有,而不是字段。

标签: sql sql-server case


【解决方案1】:

也许你需要这样的东西......

您实际上并不想要所有约会,您只想要最近的约会。对吧?

SELECT d.PatientID, d.PatientName
    -- ...[other demographic fields like DOB, gender, race]
    , a.LastVisitDate
    , a.NextApptDate
    , IsActive     = CASE WHEN a.LastVisitDate > DATEADD(YEAR, -3, GETDATE()) THEN 'YES' ELSE '' END
    , InactiveFlag = CASE WHEN d.PatientFlag = 'Inactive Patient!' THEN 'YES' ELSE '' END
FROM Demographic d
    OUTER APPLY (
        SELECT TOP(1) a.LastVisitDate, a.NextApptDate
        FROM Appointment a
        WHERE d.PatientID = a.PatientID
        ORDER BY a.LastVisitDate DESC
    ) a

【讨论】:

  • LastVisitDate 字段已经只显示最近的约会。
  • @EJF Demographic 表和 Appointment 表在 PatientID 上是否具有一对一的关系?意思是,SELECT * FROM Demographic WHERE PatientID = 1SELECT * FROM Appointment WHERE PatientID = 1,我会一直得到 1 条记录吗?
  • 人口统计表,是的。预约表包含患者过去的所有就诊和即将到来的预约,但LastVisitDate 字段显示该表中的最近一次就诊,NextApptDate 显示下一次就诊,无论安排了多少次。
  • 对,所以如果您有 1 个 Demographic 记录的 3 个约会记录,您最终会得到 Demographic 重复 3 次。您是否尝试过运行我的查询以查看它是否得到您想要的?问题是您想选择一个约会记录,并且您可能想选择最近的一个。
  • 但是每个患者不会有 3 个预约记录,因为 LastVisitDateNextApptDate 是不同的。过去我没有遇到重复行的问题,并且一直以这种方式加入人口统计和约会表。当我今天添加新的 CASE 语句时,重复开始,因为非活动指示器出于某种原因创建了一个新的不同记录,而不是仅仅添加到现有记录中。
【解决方案2】:

考虑加入聚合的约会结果集,该结果集根据PatientID 返回上次访问日期和下次约会日期。然后,您可以加入进行或 1:1 比较。

WITH appt_agg (
   SELECT PatientID
         , MAX(LastVisitDate) AS LastVisitDate
         , MIN(NextApptDate) AS NextApptDate
   FROM Appointment 
   GROUP BY PatientID
)

SELECT d.PatientID
    , d.PatientName
    , ...[other demographic fields like DOB, gender, race]

    , a.LastVisitDate
    , a.NextApptDate
    , (CASE
          WHEN a.LastVisitDate > DATEADD(yy, -3, GETDATE()) 
          THEN 'YES'
          ELSE NULL
       END) AS [Active?]
    , (CASE
          WHEN d.PatientFlag = 'Inactive Patient!' 
          THEN 'YES'
          ELSE NULL
       END) AS [Inactive Flag?]

FROM Demographic d 
LEFT JOIN appt_gg a
    ON d.PatientID = a.PatientID

【讨论】:

    猜你喜欢
    • 2021-02-06
    • 2012-11-04
    • 2012-12-12
    • 1970-01-01
    • 2019-03-04
    • 2019-06-22
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多