You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL结果转置:将多通信记录合并为单行多列的实现方案

嘿,我来帮你搞定这个SQL行转列的问题!

你现在遇到的核心问题是一对多关联导致的多行记录,需要把同一用户的不同通信方式转成单行多列。之前用子查询的方式不对,因为你没关联主表的人员ID,导致子查询返回了所有符合COMM_RID=6的记录,和主表的每一行通信记录做匹配,自然会出现重复和null。

给你两种靠谱的解决方案,兼容性和易用性都拉满:

方法一:条件聚合(几乎所有数据库都支持)

这是最通用的写法,用CASE WHEN配合聚合函数(MAX/MIN)把不同COMM_RID的值映射到单独列,再通过GROUP BY合并同一用户的记录:

SELECT 
    PRP.FIRSTNAME + ' ' + PRP.SURNAME AS FULLNAME,
    RDP.POSTNAME,
    RRP.REMARKS,
    -- 对应COMM_RID=5的手机号
    MAX(CASE WHEN PC.COMM_RID = '5' THEN PC.COMM_VALUE END) AS Mobile,
    -- 对应COMM_RID=6的呼号
    MAX(CASE WHEN PC.COMM_RID = '6' THEN PC.COMM_VALUE END) AS Radio,
    -- 对应COMM_RID=7的传呼机号
    MAX(CASE WHEN PC.COMM_RID = '7' THEN PC.COMM_VALUE END) AS Pager
FROM 
    -- 这里替换成你原来的主表关联逻辑,下面是示例关联条件
    YOUR_PERSON_TABLE PRP
INNER JOIN 
    RDP ON PRP.RDP_ID = RDP.ID
INNER JOIN 
    RRP ON PRP.RRP_ID = RRP.ID
-- 用LEFT JOIN避免没有通信记录的用户被过滤
LEFT JOIN 
    PERREC_COMMS PC ON PRP.PERSON_ID = PC.PERSON_ID
-- 按用户的唯一标识和需要保留的字段分组
GROUP BY 
    PRP.PERSON_ID, -- 一定要加这个唯一ID,避免同名用户被合并
    PRP.FIRSTNAME + ' ' + PRP.SURNAME, 
    RDP.POSTNAME, 
    RRP.REMARKS

为什么这个能行?

  • CASE WHEN会把符合条件的COMM_VALUE筛选出来,不符合的返回null;
  • MAX函数会自动忽略null值,只保留该用户对应通信方式的有效值;
  • GROUP BY把同一用户的所有通信记录合并成一行,完美解决重复问题。

方法二:PIVOT(适用于SQL Server、Oracle等支持的数据库)

如果你的数据库支持PIVOT语法,写法会更简洁:

SELECT 
    FULLNAME,
    POSTNAME,
    REMARKS,
    [5] AS Mobile,
    [6] AS Radio,
    [7] AS Pager
FROM (
    -- 先查询出基础数据集:用户信息 + 通信RID + 通信值
    SELECT 
        PRP.FIRSTNAME + ' ' + PRP.SURNAME AS FULLNAME,
        RDP.POSTNAME,
        RRP.REMARKS,
        PC.COMM_RID,
        PC.COMM_VALUE
    FROM 
        YOUR_PERSON_TABLE PRP
    INNER JOIN 
        RDP ON PRP.RDP_ID = RDP.ID
    INNER JOIN 
        RRP ON PRP.RRP_ID = RRP.ID
    LEFT JOIN 
        PERREC_COMMS PC ON PRP.PERSON_ID = PC.PERSON_ID
) AS SourceData
PIVOT (
    MAX(COMM_VALUE) -- 用MAX确保每个用户每个RID只取一个值
    FOR COMM_RID IN ([5], [6], [7]) -- 指定要转成列的RID值
) AS PivotedData

额外提醒

  1. 用LEFT JOIN关联PERREC_COMMS:如果某个用户没有某类通信方式,对应的列会显示null,而不是直接被排除出结果;
  2. 一定要按用户唯一ID分组:如果有同名用户,仅按姓名分组会把他们的记录合并,导致数据错误;
  3. 注意COMM_RID的类型:如果它是数字类型,去掉单引号(比如COMM_RID = 5而不是'5'),匹配数据库实际字段类型。

至于你之前尝试的子查询,其实可以改成关联子查询来解决,但不如条件聚合稳妥(比如如果一个用户有多个同一RID的通信记录,子查询会报错):

SELECT 
    PRP.FIRSTNAME + ' ' + PRP.SURNAME AS FULLNAME,
    RDP.POSTNAME,
    RRP.REMARKS,
    -- 关联主表的PERSON_ID,只取当前用户的通信值
    (SELECT COMM_VALUE FROM PERREC_COMMS PC WHERE PC.PERSON_ID = PRP.PERSON_ID AND PC.COMM_RID = '6') AS Radio
FROM 
    YOUR_PERSON_TABLE PRP
INNER JOIN 
    RDP ON PRP.RDP_ID = RDP.ID
INNER JOIN 
    RRP ON PRP.RRP_ID = RRP.ID

内容的提问来源于stack exchange,提问作者TheMiddle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:45:31