SQL根据条件生成新列 将患者多剂接种多条记录合并为单行实现方法
你需要实现的是典型的行转列(多线转宽表)需求,以下是不同场景下的SQL实现方案:
前提假设
假设你的表名为vaccination_records,核心字段包含:
patient_name:患者姓名dose_number:接种剂次vaccination_date:接种日期vaccine_type:疫苗种类
你可以根据自己的实际表字段调整以下代码。
通用方案(兼容所有SQL数据库)
用条件聚合实现,兼容性最高,适合剂次数量固定的场景:
SELECT patient_name, -- 第1剂信息 MAX(CASE WHEN dose_number = 1 THEN vaccination_date END) AS dose_1_date, MAX(CASE WHEN dose_number = 1 THEN vaccine_type END) AS dose_1_vaccine, -- 第2剂信息 MAX(CASE WHEN dose_number = 2 THEN vaccination_date END) AS dose_2_date, MAX(CASE WHEN dose_number = 2 THEN vaccine_type END) AS dose_2_vaccine, -- 第3剂及以上按相同规则补充即可 MAX(CASE WHEN dose_number = 3 THEN vaccination_date END) AS dose_3_date, MAX(CASE WHEN dose_number = 3 THEN vaccine_type END) AS dose_3_vaccine FROM vaccination_records GROUP BY patient_name;
注:这里使用
MAX聚合函数是因为同一名患者同一剂次只会有一条有效记录,MAX/MIN均可,作用是取出唯一的非空值。
动态列方案(剂次数量不固定场景)
如果剂次数量不固定,不想手动修改SQL补全新的剂次,可以用动态SQL实现,以下是MySQL版本示例:
-- 拼接动态查询SQL SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT 'MAX(CASE WHEN dose_number = ', dose_number, ' THEN vaccination_date END) AS dose_', dose_number, '_date,', 'MAX(CASE WHEN dose_number = ', dose_number, ' THEN vaccine_type END) AS dose_', dose_number, '_vaccine' ) INTO @sql FROM vaccination_records; SET @sql = CONCAT('SELECT patient_name, ', @sql, ' FROM vaccination_records GROUP BY patient_name'); -- 执行动态SQL PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
PIVOT语法方案(支持PIVOT的数据库可用)
如果使用SQL Server、Oracle、PostgreSQL 15及以上版本,也可以用原生PIVOT语法实现,以下是SQL Server示例:
SELECT * FROM ( SELECT patient_name, 'dose_' + CAST(dose_number AS VARCHAR) + '_' + col AS pivot_col, val FROM vaccination_records CROSS APPLY ( VALUES ('date', CAST(vaccination_date AS VARCHAR(20))), ('vaccine', vaccine_type) ) c(col, val) ) src PIVOT ( MAX(val) FOR pivot_col IN ( dose_1_date, dose_1_vaccine, dose_2_date, dose_2_vaccine, dose_3_date, dose_3_vaccine ) ) pvt;
内容的提问来源于stack exchange,提问作者Ph14 Woozies
相关产品推荐
相关产品推荐

