Microsoft SQL Server:如何将多组风险统计查询结果合并为单行输出
修正SQL Server语句实现一行显示风险统计
首先,你的原语句存在几个问题:一是语法不符合SQL Server规范,试图在FROM子句里直接用逗号连接两个SELECT子查询是行不通的;二是你给高、中风险写的条件完全一致,这显然不符合实际业务逻辑,我先假设了一些合理的风险划分规则,你可以根据真实需求调整。
另外,关于日期转换的部分,FORMAT(getdate(), 'yyyyMMdd')虽然直观,但在大数据量场景下性能不如CONVERT函数,我换成了更高效的写法,还把日期值存到变量里避免重复计算。
写法一:子查询作为列(直观易读)
这种方式每个风险统计是独立的子查询,逻辑清晰,适合各风险规则差异较大的场景:
SELECT -- 高风险:三个日期均已过期 (SELECT COUNT(DISTINCT PatientKey) FROM dbo.vw_FactReferral WHERE PrescriptionDueDateKey <= CONVERT(int, CONVERT(varchar(8), GETDATE(), 112)) AND OrderConfirmationDueDateKey <= CONVERT(int, CONVERT(varchar(8), GETDATE(), 112)) AND NextDeliveryDueDateKey <= CONVERT(int, CONVERT(varchar(8), GETDATE(), 112))) AS HighRisk, -- 中风险:前两个日期过期,第三个未过期(请根据业务调整) (SELECT COUNT(DISTINCT PatientKey) FROM dbo.vw_FactReferral WHERE PrescriptionDueDateKey <= CONVERT(int, CONVERT(varchar(8), GETDATE(), 112)) AND OrderConfirmationDueDateKey <= CONVERT(int, CONVERT(varchar(8), GETDATE(), 112)) AND NextDeliveryDueDateKey > CONVERT(int, CONVERT(varchar(8), GETDATE(), 112))) AS MediumRisk, -- 低风险:至少一个日期未过期(请根据业务调整) (SELECT COUNT(DISTINCT PatientKey) FROM dbo.vw_FactReferral WHERE PrescriptionDueDateKey > CONVERT(int, CONVERT(varchar(8), GETDATE(), 112)) OR OrderConfirmationDueDateKey > CONVERT(int, CONVERT(varchar(8), GETDATE(), 112)) OR NextDeliveryDueDateKey > CONVERT(int, CONVERT(varchar(8), GETDATE(), 112))) AS LowRisk
写法二:CASE WHEN + 聚合(性能更优)
这种方式只需要扫描一次表,数据量大时性能更好,推荐优先使用:
-- 先定义今天的日期变量,避免重复计算 DECLARE @TodayInt INT = CONVERT(int, CONVERT(varchar(8), GETDATE(), 112)) SELECT -- 高风险统计 COUNT(DISTINCT CASE WHEN PrescriptionDueDateKey <= @TodayInt AND OrderConfirmationDueDateKey <= @TodayInt AND NextDeliveryDueDateKey <= @TodayInt THEN PatientKey END) AS HighRisk, -- 中风险统计(请根据业务调整条件) COUNT(DISTINCT CASE WHEN PrescriptionDueDateKey <= @TodayInt AND OrderConfirmationDueDateKey <= @TodayInt AND NextDeliveryDueDateKey > @TodayInt THEN PatientKey END) AS MediumRisk, -- 低风险统计(请根据业务调整条件) COUNT(DISTINCT CASE WHEN NOT (PrescriptionDueDateKey <= @TodayInt AND OrderConfirmationDueDateKey <= @TodayInt) THEN PatientKey END) AS LowRisk FROM dbo.vw_FactReferral
关键提醒:
- 务必根据你的实际业务规则调整每个风险对应的WHERE/CASE条件,我这里只是示例;
CONVERT(varchar(8), GETDATE(), 112)会生成yyyyMMdd格式的字符串,再转成int和你的日期键字段匹配,比FORMAT更高效;- 使用
COUNT(DISTINCT PatientKey)确保每个患者只被统计一次,符合你的需求。
内容的提问来源于stack exchange,提问作者Farrukh
相关产品推荐
相关产品推荐

