提问人:Christopher Thoms 提问时间:10/21/2023 最后编辑:Dale KChristopher Thoms 更新时间:10/21/2023 访问量:60
创建一个带有 CASE 语句的标志,拉动多个表?
Create a flag with a CASE statement pulling on multiple tables?
问:
运行 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
答:
操作员的优先级通常令人惊讶并抓住人们。除了代码之外,我们还有这个:OR
AND
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。
评论
omed.OrderStatusDSC is distinct from 'Canceled'
这可能离题很远,因为并非所有列名都以别名为前缀,所以我在这里猜测了一下,这也可能不是很好,但我正在尝试简化查询。
我会创建一个视图,其中包含符合用药标准的简单不同患者列表。例如
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,则“标志”将为 0CASE
PatientID
EDW.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
粗略地说,我已经接受了您的第一个查询并将第二个查询添加为外部连接表(删除不需要的投影列),如果该行存在,则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')
评论