Oracle数据库按SSN分组,将同一人员的多Person ID转为单行多列的咨询
简单实现Oracle同一人员多Person ID合并到单行多列
嘿,这个需求我之前帮同事处理过,对于SQL经验不多的朋友来说,用聚合函数+条件判断的组合就足够简单好上手,不用搞复杂的存储过程或者高级窗口函数,逻辑也容易懂!
假设你的表结构
先假设你的人员信息表叫person_info,核心字段包括:
person_id:系统生成的唯一IDssn:社保号(用来判断是否为同一人)name、address等其他人口统计字段
具体实现步骤
1. 先给每个SSN下的Person ID编序号
用ROW_NUMBER()窗口函数,给同一个SSN下的每条记录分配一个递增的序号(1、2、3...),这样我们就能区分同一个人的不同Person ID:
WITH ranked_persons AS ( SELECT ssn, name, address, person_id, -- 按SSN分组,给每个Person ID排序编号 ROW_NUMBER() OVER (PARTITION BY ssn ORDER BY person_id) AS id_rank FROM person_info )
2. 把不同序号的Person ID转成单独的列
用MAX()结合CASE条件判断,把每个序号对应的Person ID提取到单独的列里,最后按SSN和其他人口信息分组:
-- 接上上面的CTE SELECT ssn, name, address, -- 提取第1个Person ID MAX(CASE WHEN id_rank = 1 THEN person_id END) AS person_id_1, -- 提取第2个Person ID,按需添加更多 MAX(CASE WHEN id_rank = 2 THEN person_id END) AS person_id_2, MAX(CASE WHEN id_rank = 3 THEN person_id END) AS person_id_3 FROM ranked_persons GROUP BY ssn, name, address;
关键细节说明
- 为什么用
MAX()?因为分组后同一个SSN会对应多行记录,CASE语句只会保留对应序号的Person ID,其他行都是NULL,MAX()能帮我们把非空的ID值筛选出来,正好对应到每一列。 - 不知道要加多少个
person_id_n列?可以先查一下同一个SSN最多有多少个重复记录:
SELECT ssn, COUNT(*) AS duplicate_count FROM person_info GROUP BY ssn ORDER BY duplicate_count DESC;
根据这个结果来调整CASE语句的数量就行。
方案优势
这个写法逻辑直白,代码也不复杂,新手很容易理解和修改,不需要掌握太高级的SQL语法,完全能满足你的需求~
内容的提问来源于stack exchange,提问作者Miles M
相关产品推荐
相关产品推荐

