创建一个带有 CASE 语句的标志,拉动多个表?

Create a flag with a CASE statement pulling on multiple tables?

提问人:Christopher Thoms 提问时间:10/21/2023 最后编辑:Dale KChristopher Thoms 更新时间:10/21/2023 访问量:60

问:

运行 SQL Server Management Studio v18.1。

我有一个查询,返回 153 条符合特定程序代码和日期条件的患者就诊记录。我还有另一个查询,它返回与这些患者相关的药物(数千行)。我想将这些查询组合在一起,如果某些药物与患者相关,则将 153 名患者遇到的每一次标记为 1,否则标记为 0。我目前的尝试是使用 CASE WHEN 语句,但它运行了很长时间并返回不符合我的过程日期和类型条件的行。我认为我在各种连接方面做错了什么,或者 CASE WHEN 不是正确的解决方案。任何帮助将不胜感激!

下面是返回 153 个患者遭遇的查询:

SELECT TOP(1000) pe.PatientEncounterID
      ,pt.MRN
      ,pe.HospitalAccountID
      ,hacpt.CPT
      ,hacpt.CPTDSC
      ,hacpt.ProcedurePerformDT
      ,pe.EncounterTypeDSC
      ,pe.AppointmentStatusDSC
      ,pe.VisitTypeID
      ,pe.VisitTypeDSC
      ,hacpt.PerformingProviderID
      ,prv.ProviderNM
      ,prv.PrimarySpecialtyDSC
      ,pe.PatientDetailTypeDSC
 FROM EDW.Encounter.PatientEncounter pe
 JOIN EDW.Billing.HospitalAccountCPT hacpt ON hacpt.HospitalAccountID = pe.HospitalAccountID
 JOIN EDW.Provider.Provider prv ON prv.ProviderID = pe.VisitProviderID
 JOIN EDW.Patient.Patient pt ON pt.PatientID = pe.PatientID
 WHERE 
  hacpt.ProcedurePerformDT > '2023-05-01'
  AND pe.AppointmentStatusID = 2
  AND hacpt.CPT IN ('00731', '00732', '00740', '00810', '00811',
'00813', '0397T', '3130F', '43254', '43266', '43273', '44360', '44361',
'44370', '44383', '44384', '44397', '44402', '44403', '45347', '45349',
'45387', '45389', '45390', '47550', '47552', '47553', '47554', '76975',
'9124', 'C9779')
AND prv.ProviderID IN ('30638', '35018', '08707', '08700', '29288', '08711', '32763', '33093', '28411', '28326')

这是我的药物清单查询:

SELECT    omed.PatientEncounterID
      ,omed.StartDT
      ,omed.EndDT
      ,omed.DiscontinueDTS
      ,emed.EpicMedicationID
      ,emed.GenericProductID
      ,emed.MedicationNM
      ,emed.PharmaceuticalClassCD
      ,emed.PharmaceuticalClassDSC
      ,emed.PharmaceuticalSubclassCD
      ,emed.PharmaceuticalSubclassDSC
      ,emed.GrouperMedicationID
      ,CASE WHEN emed.ProductTypeID = 2 THEN 'OTC' ELSE 'Prescription' END AS MedType
    FROM Reference.EpicMedication emed
    LEFT JOIN Orders.OrderMedication omed ON omed.EpicMedicationID = emed.EpicMedicationID
    WHERE omed.EndDT > GETDATE()
        AND (omed.DiscontinueDTS IS NULL OR omed.DiscontinueDTS > GETDATE())
        AND (
        (omed.OrderStatusDSC IS NULL) OR omed.OrderStatusDSC NOT IN ('Canceled') )
        AND (GenericNM LIKE '%apixaban%'
        OR GenericNM LIKE '%Aspirin%'
        OR GenericNM LIKE '%Cilostazol%'
        OR GenericNM LIKE '%Clopidogrel%'
        OR GenericNM LIKE '%Dapigatran%'
        OR GenericNM LIKE '%Edoxaban%'
        OR GenericNM LIKE '%Prasugrel%'
        OR GenericNM LIKE '%Ticlopidine%'
        OR GenericNM LIKE '%Rivaroxaban%'
        OR GenericNM LIKE '%Warfarin%')
    GROUP BY omed.PatientEncounterID
      ,omed.StartDT
      ,omed.EndDT
      ,omed.DiscontinueDTS
      ,emed.EpicMedicationID
      ,emed.GenericProductID
      ,emed.MedicationNM
      ,emed.PharmaceuticalClassCD
      ,emed.PharmaceuticalClassDSC
      ,emed.PharmaceuticalSubclassCD
      ,emed.PharmaceuticalSubclassDSC
      ,emed.GrouperMedicationID
      ,CASE WHEN emed.ProductTypeID = 2 THEN 'OTC' ELSE 'Prescription' END

这是我将两者结合起来的尝试。同样,我想要/期望的是返回 153 行,就像我的第一个查询一样,但增加了一列Med_Flg但我得到的行与我的 hacpt 不匹配。程序执行DT > '2023-05-01' 或 hacpt。CPT IN 标准。

SELECT TOP(1000) pe.PatientEncounterID
      ,pt.MRN
      ,pe.HospitalAccountID
      ,hacpt.CPT
      ,hacpt.CPTDSC
      ,hacpt.ProcedurePerformDT
      ,pe.EncounterTypeDSC
      ,pe.AppointmentStatusDSC
      ,pe.VisitTypeID
      ,pe.VisitTypeDSC
      ,hacpt.PerformingProviderID
      ,prv.ProviderNM
      ,prv.PrimarySpecialtyDSC
      ,pe.PatientDetailTypeDSC
      ,CASE WHEN (emed.GenericNM LIKE '%apixaban%'
        OR emed.GenericNM LIKE '%Aspirin%'
        OR emed.GenericNM LIKE '%Cilostazol%'
        OR emed.GenericNM LIKE '%Clopidogrel%'
        OR emed.GenericNM LIKE '%Dapigatran%'
        OR emed.GenericNM LIKE '%Edoxaban%'
        OR emed.GenericNM LIKE '%Prasugrel%'
        OR emed.GenericNM LIKE '%Ticlopidine%'
        OR emed.GenericNM LIKE '%Rivaroxaban%'
        OR emed.GenericNM LIKE '%Warfarin%'
        ) THEN 1 ELSE 0 END AS "Med_Flg"
 FROM EDW.Encounter.PatientEncounter pe
 JOIN EDW.Billing.HospitalAccountCPT hacpt ON hacpt.HospitalAccountID = pe.HospitalAccountID
 JOIN EDW.Provider.Provider prv ON prv.ProviderID = pe.VisitProviderID
 JOIN EDW.Patient.Patient pt ON pt.PatientID = pe.PatientID
    LEFT JOIN Reference.EpicMedication emed
    LEFT JOIN Orders.OrderMedication omed ON omed.EpicMedicationID = emed.EpicMedicationID ON pe.PatientEncounterID = omed.PatientEncounterID
 WHERE 
  hacpt.ProcedurePerformDT > '2023-05-01'
  AND AppointmentStatusID = 2
  AND CPT IN ('00731', '00732', '00740', '00810', '00811',
'00813', '0397T', '3130F', '43254', '43266', '43273', '44360', '44361',
'44370', '44383', '44384', '44397', '44402', '44403', '45347', '45349',
'45387', '45389', '45390', '47550', '47552', '47553', '47554', '76975',
'9124', 'C9779')
AND prv.ProviderID IN ('30638', '35018', '08707', '08700', '29288', '08711', '32763', '33093', '28411', '28326')
AND (omed.OrderStatusDSC IS NULL ) 
  OR (omed.OrderStatusDSC NOT IN ('Canceled')
  )
  AND omed.EndDT > GETDATE()
GROUP BY pe.PatientEncounterID
      ,pt.MRN
      ,prv.ProviderNM
      ,hacpt.ProcedurePerformDT
      ,hacpt.CPT
      ,pe.HospitalAccountID
      ,hacpt.CPTDSC
      ,pe.EncounterTypeDSC
      ,pe.AppointmentStatusDSC
      ,pe.VisitTypeID
      ,pe.VisitTypeDSC
      ,hacpt.PerformingProviderID
      ,prv.PrimarySpecialtyDSC
      ,pe.PatientDetailTypeDSC
      ,CASE WHEN (GenericNM LIKE '%apixaban%'
        OR GenericNM LIKE '%Aspirin%'
        OR GenericNM LIKE '%Cilostazol%'
        OR GenericNM LIKE '%Clopidogrel%'
        OR GenericNM LIKE '%Dapigatran%'
        OR GenericNM LIKE '%Edoxaban%'
        OR GenericNM LIKE '%Prasugrel%'
        OR GenericNM LIKE '%Ticlopidine%'
        OR GenericNM LIKE '%Rivaroxaban%'
        OR GenericNM LIKE '%Warfarin%'
        ) THEN 1 ELSE 0 END
SQL-Server 联接 案例

评论

2赞 jarlh 10/21/2023
让您轻松获得帮助 - 简化!通过适当的最小可重复示例,您将更快地获得更好的答案!
0赞 Chris Albert 10/21/2023
SSMS 的版本在这里不是特别重要,SQL Server 的版本是。
0赞 Dale K 10/21/2023
强调最小,我们不需要您的实际查询,只需要减少一个来演示问题。还有一种情况是表达式而不是语句。
1赞 Joel Coehoorn 10/21/2023
在更高层次上,您始终可以通过将这些查询 JOINing 作为子查询来组合这些查询,然后使用条件聚合或大小写表达式来投影所需的新列。当多个药物匹配时,这将导致重复行。您可以使用较长的 GROUP BY 子句来处理此问题,但 row_number() 策略可能更有效。
1赞 Dale K 10/21/2023
最小值意味着您删除了大部分列,因为无论您显示 20 还是 2 都不会改变逻辑。我猜你也可以删除大部分联接。但是,您也应该向我们提供示例数据和期望的结果。总而言之,创建这样一个最小的示例不仅可以帮助您更好地理解问题,更好地理解 SQL,而且人们在创建最小示例时经常会解决自己的问题,因为他们意识到实际发生了什么。

答:

0赞 Joel Coehoorn 10/21/2023 #1

操作员的优先级通常令人惊讶并抓住人们。除了代码之外,我们还有这个:ORAND

AND (omed.OrderStatusDSC IS NULL ) 
  OR (omed.OrderStatusDSC NOT IN ('Canceled')
  )

它可能应该是这样的:

AND (omed.OrderStatusDSC IS NULL  
  OR omed.OrderStatusDSC NOT IN ('Canceled')
  )

我可能会写成:

coalesce(omed.OrderStatusDSC, '') <> 'Canceled'

否则,这里的代码比我有时间审查的要多。

另外,看起来从第二个查询中加入其他表以添加药物意味着原始 153 个患者行中的每一个都可能在结果中出现多次(每个匹配的药物一次),解决此问题的策略是按所需的输出列分组。

这种策略可以奏效,但也有其他选择。一个常见的选择是改用意志选择的分区和排序,这样我们就可以只包括 row_number() 为 1 的结果。这同样有效,运行速度更快,并且需要更少的代码。row_number() over

另一种选择是对附加查询中的表使用操作而不是 JOIN,其中 APPLY 限制为一行。APPLY

最好的选择可能是在将其他药物查询与患者查询相结合之前对其进行更多调整,以将其减少到仅包含第一个查询中的键的单个列。然后用代替 LEFT JOIN,所以 NULL 是 0,其他任何东西都是 1。

评论

0赞 jarlh 10/22/2023
在 SQL Server 2022 中,您可以执行 .omed.OrderStatusDSC is distinct from 'Canceled'
0赞 Alan Schofield 10/21/2023 #2

这可能离题很远,因为并非所有列名都以别名为前缀,所以我在这里猜测了一下,这也可能不是很好,但我正在尝试简化查询。

我会创建一个视图,其中包含符合用药标准的简单不同患者列表。例如

CREATE VIEW PatientsOnSpecificMeds AS
SELECT DISTINCT pe.PatientID
FROM Reference.EpicMedication emed
    JOIN Orders.OrderMedication omed ON omed.EpicMedicationID = emed.EpicMedicationID 
    JOIN EDW.Patient.Patient pt ON pt.PatientID = pe.PatientID
    WHERE omed.OrderStatusDSC IS NULL
        OR omed.OrderStatusDSC NOT IN ('Canceled')
        AND omed.EndDT > GETDATE()
        AND emed.GenericNM LIKE '%apixaban%' OR
            emed.GenericNM LIKE '%Aspirin%' OR
            emed.GenericNM LIKE '%Cilostazol%' OR
            emed.GenericNM LIKE '%Clopidogrel%' OR
            emed.GenericNM LIKE '%Dapigatran%' OR
            emed.GenericNM LIKE '%Edoxaban%' OR
            emed.GenericNM LIKE '%Prasugrel%' OR
            emed.GenericNM LIKE '%Ticlopidine%' OR
            emed.GenericNM LIKE '%Rivaroxaban%' OR
            emed.GenericNM LIKE '%Warfarin%'

现在,在您的主查询中,您不需要任何一个,您只需使用表中的左联接即可连接到上面的视图。如果视图中的 PatientID 为 null,则“标志”将为 0CASEPatientIDEDW.Patient.Patient

例如(不使用别名,因为它不是完整的代码)

IIF(PatientsOnSpecificMeds.PatientID ISNULL, 0,1) AS Med_flg

或者,如果使用旧版本的 SQL Server

CASE WHEN PatientsOnSpecificMeds.PatientID IS NULL THEN 1 ELSE 0 END AS Med_Flg
0赞 diarmuid 10/21/2023 #3

粗略地说,我已经接受了您的第一个查询并将第二个查询添加为外部连接表(删除不需要的投影列),如果该行存在,则med_flg为 1,否则为 0 - HTH

SELECT TOP(1000) pe.PatientEncounterID
  ,pt.MRN
  ,pe.HospitalAccountID
  ,hacpt.CPT
  ,hacpt.CPTDSC
  ,hacpt.ProcedurePerformDT
  ,pe.EncounterTypeDSC
  ,pe.AppointmentStatusDSC
  ,pe.VisitTypeID
  ,pe.VisitTypeDSC
  ,hacpt.PerformingProviderID
  ,prv.ProviderNM
  ,prv.PrimarySpecialtyDSC
  ,pe.PatientDetailTypeDSC
  ,case when meds.patientEncounterID IS NOT NULL THEN 1 ELSE 0 END AS "Med_Flg"
   FROM EDW.Encounter.PatientEncounter pe
   JOIN EDW.Billing.HospitalAccountCPT hacpt ON hacpt.HospitalAccountID 
= pe.HospitalAccountID
   JOIN EDW.Provider.Provider prv ON prv.ProviderID = pe.VisitProviderID
   JOIN EDW.Patient.Patient pt ON pt.PatientID = pe.PatientID
   left join (select omed.PatientEncounterID FROM 
Reference.EpicMedication emed
        LEFT JOIN Orders.OrderMedication omed ON omed.EpicMedicationID = 
emed.EpicMedicationID
        WHERE omed.EndDT > GETDATE()
        AND (omed.DiscontinueDTS IS NULL OR omed.DiscontinueDTS > 
GETDATE())
        AND (
    (omed.OrderStatusDSC IS NULL) OR omed.OrderStatusDSC NOT IN 
('Canceled') )
        AND (GenericNM LIKE '%apixaban%'
        OR GenericNM LIKE '%Aspirin%'
        OR GenericNM LIKE '%Cilostazol%'
        OR GenericNM LIKE '%Clopidogrel%'
        OR GenericNM LIKE '%Dapigatran%'
        OR GenericNM LIKE '%Edoxaban%'
        OR GenericNM LIKE '%Prasugrel%'
        OR GenericNM LIKE '%Ticlopidine%'
        OR GenericNM LIKE '%Rivaroxaban%'
        OR GenericNM LIKE '%Warfarin%')
    GROUP BY omed.PatientEncounterID
       ,omed.StartDT
       ,omed.EndDT
      ,omed.DiscontinueDTS
      ,emed.EpicMedicationID
      ,emed.GenericProductID
      ,emed.MedicationNM
      ,emed.PharmaceuticalClassCD
      ,emed.PharmaceuticalClassDSC
      ,emed.PharmaceuticalSubclassCD
      ,emed.PharmaceuticalSubclassDSC
      ,emed.GrouperMedicationID
      ,CASE WHEN emed.ProductTypeID = 2 THEN 'OTC' ELSE 'Prescription' 
END
      ) meds on meds.patientEncounterID = pe.PatientEncounterID 
 WHERE hacpt.ProcedurePerformDT > '2023-05-01'
 AND pe.AppointmentStatusID = 2
 AND hacpt.CPT IN ('00731', '00732', '00740', '00810', '00811',
'00813', '0397T', '3130F', '43254', '43266', '43273', '44360', '44361',
'44370', '44383', '44384', '44397', '44402', '44403', '45347', '45349',
'45387', '45389', '45390', '47550', '47552', '47553', '47554', '76975',
'9124', 'C9779')
 AND prv.ProviderID IN ('30638', '35018', '08707', '08700', '29288', 
'08711', '32763', '33093', '28411', '28326')