【问题标题】:SQL Subquery to count number of records based on difference between 2 datesSQL子查询根据2个日期之间的差异计算记录数
【发布时间】:2017-04-05 15:25:26
【问题描述】:

我正在查询在 2016 年 1 月 1 日至 2016 年 12 月 31 日期间入院并死亡的患者的结果集。

作为结果集的一部分,我需要包含一个列(“之前入院次数”),该列给出了患者在截至其最终入院日期的 12 个月期间内所有之前入院的总数。

因此,如果患者在 2016 年 6 月 1 日入院并死亡,并且在 2015 年 7 月 1 日和 2015 年 9 月 30 日有 2 次入院,则此列中的总数将为“2”。

因此逻辑需要是:如果患者在 xx/xx/xxxx 日期入院并死亡,则计算入院日期在 xx/xx/xxxx 后 365 天内同一患者的先前入院次数。

我已尝试将其作为以下子查询,但遇到 2 个问题:

1) 查询似乎在计算表中的所有入院记录,而不仅仅是与个别患者相关的记录。

2) 结果排除了最后一次就诊的所有患者(即他们之前没有就诊)。如果他们之前没有出席,我希望列中出现 0。

请任何人就正确的方法/语法提出建议吗?

这是我尝试过的子查询:

SELECT DISTINCT
EP.Patient_Id
,EP.Admission_Date 'Final Admission Date'
,(
    SELECT COUNT(*)
    FROM Inpatients.vw_IP_Episodes IP
    WHERE DATEDIFF(day,IP.Admission_Date,EP.Admission_Date) < '365'
    AND IP.Discharge_Method != 'Patient died'
 ) 
 AS 'No of Prior Admissions'

FROM Inpatients.vw_IP_Episodes EP
WHERE EP.Admission_Date BETWEEN '01/01/2016' AND '31/12/2016'
AND EP.Discharge_Method = 'Patient died'

GROUP BY EP.Patient_Id, EP.Admission_Date

【问题讨论】:

  • 我认为您的子查询也应该过滤 IP.Patient_Id = EP.Patient_Id - 这应该可以解决您的问题 #1。
  • 您也可以考虑重写您的 WHERE 语句以使用适当的 SARG 进行日期过滤。 IP.Admission_Date >= DATEADD(天,-365,EP.Admission_Date)。如果您在 Admission_Date 上有任何索引,这将帮助优化器选择正确的索引。最后,如果死亡的出院日期和入院日期不相同,则与更多业务相关,如果您担心死亡日期,您可能会切换到 EP 的出院日期。
  • 谢谢@Anssssss。实际上,这解决了这两个问题,尽管它给了我另一个问题。返回的结果是一些计数加倍。我已将子查询 SELECT 修改为在主键 SELECT COUNT(DISTINCT IP.Inpatient_Episode_Primary_Key) 上不同,但这没有区别。
  • 谢谢@AnthonyHancock 我已将优化代码应用于我的查询。是的,这是关于入院日期和出院日期之间潜在差异的一个有效点。报告的重点是入院日期,而不是实际死亡日期(即使比入院晚了几天),所以这是我们采取的参考点。
  • @Jon295087,不确定为什么会发生加倍...也许您可以通过查看子查询为特定 EP.Patient_Id 和 EP.Admission_Date 值找到哪些行来调试问题。另外,没什么大不了的,但我认为最后的 GROUP BY 是不必要的(因为您没有在主查询中执行任何聚合函数 - COUNT(*) 在子查询中)。

标签: sql-server sql-server-2008 tsql


【解决方案1】:

感谢与其他人的讨论,这是解决方案:

SELECT DISTINCT
EP.Patient_Id
,EP.Admission_Date 'Final Admission Date'
,(
    SELECT COUNT(DISTINCT IP.Admission_Date)
    FROM Inpatients.vw_IP_Episodes IP
    WHERE IP.Admission_Date >= DATEADD(day, -365, EP.Admission_Date)
    AND IP.Patient_Id = EP.Patient_Id
    AND IP.Discharge_Method != 'Patient died'
 ) 
 AS 'No of Prior Admissions'

FROM Inpatients.vw_IP_Episodes EP
WHERE EP.Admission_Date BETWEEN '01/01/2016' AND '31/12/2016'
AND EP.Discharge_Method = 'Patient died'

GROUP BY EP.Patient_Id, EP.Admission_Date

【讨论】:

    【解决方案2】:

    CTE 可能是删除重复项的最佳选择。

    ;WITH cte AS(SELECT EP.Patient_Id
            ,EP.Admission_Date 'Final Admission Date'
            , ROW_NUMBER() OVER (PARTITION BY EP.Patient_Id ORDER BY EP.Admission_Date DESC) AS Rownum  
            , (SELECT  COUNT(*) AS [No of Prior Admissions]
                    FROM Inpatients.vw_IP_Episodes IP
                    WHERE Admission_Date >= DATEADD(day, -365, EP.Admission_Date)
                    AND Admission_Date < EP.Admission_Date
                    AND IP.Patient_Id = EP.Patient_Id
                    ) [No of Prior Admissions]
        FROM Inpatients.vw_IP_Episodes EP
        WHERE EP.Admission_Date BETWEEN '01/01/2016' AND '31/12/2016'
        AND EP.Discharge_Method = 'Patient died'
    )
    
    SELECT *
    FROM cte
    WHERE Rownum = 1;
    

    【讨论】:

    • 嗨@Wendy,恐怕这不会运行。
    • Msg 102, Level 15, State 1, Line 9 Incorrect syntax near ')'.
    • 我已经在同一天编辑了查询。也没用?
    猜你喜欢
    • 1970-01-01
    • 2010-11-08
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    相关资源
    最近更新 更多