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

SQL对比两列数据 同值返回单行异值拆分为多行的实现方法

需求背景

存在员工表emp,表中存储员工姓名、两个联系号码字段,样例数据如下:

emp_name contact1 contact2
Harish  123      123
Manish  345      567
Ganesh  678      678

输出规则

  • 若同一员工的contact1与contact2值相同,仅返回1行记录,内容为员工姓名+对应联系方式
  • 若两个联系号码值不同,拆分为2行返回,每行分别对应员工姓名+其中一个联系方式
    期望输出结果:
emp_name contact
Harish  123
Ganesh  678
Manish  345
Manish  567
可落地的SQL实现方案

以下写法覆盖主流数据库场景,可根据自身使用的数据库选型:

  • 通用兼容写法(全数据库支持,无版本/语法限制)
    利用UNION ALL拼接结果集,第二部分仅取两个号码不相等的记录,天然避免重复行,性能最优:
    SELECT emp_name, contact1 AS contact
    FROM emp
    UNION ALL
    SELECT emp_name, contact2 AS contact
    FROM emp
    WHERE contact1 <> contact2
    -- 若字段允许为NULL,可补充空值判断逻辑:
    -- OR (contact1 IS NULL AND contact2 IS NOT NULL) 
    -- OR (contact1 IS NOT NULL AND contact2 IS NULL)
    ORDER BY emp_name, contact;
    
  • 行转列函数写法(支持UNPIVOT语法的数据库:Oracle 11g+、SQL Server、PostgreSQL等)
    用UNPIVOT完成列转行,加DISTINCT过滤值重复产生的多余行,语法简洁:
    SELECT DISTINCT emp_name, contact
    FROM emp
    UNPIVOT (
        contact FOR contact_type IN (contact1, contact2)
    ) AS t
    ORDER BY emp_name, contact;
    
  • 横向连接写法(支持LATERAL语法的数据库:PostgreSQL、MySQL 8.0.14+等)
    通过侧视图对每行员工数据做号码去重,逻辑清晰可读性强:
    SELECT e.emp_name, v.contact
    FROM emp e,
    LATERAL (
        SELECT contact1 AS contact 
        UNION 
        SELECT contact2 AS contact
    ) v
    ORDER BY e.emp_name, v.contact;
    
  • 交叉枚举写法(所有支持子查询的数据库通用)
    通过交叉连接构造序号枚举值,匹配对应联系方式后去重:
    SELECT DISTINCT 
        e.emp_name,
        CASE WHEN c.seq = 1 THEN e.contact1 ELSE e.contact2 END AS contact
    FROM emp e
    CROSS JOIN (SELECT 1 AS seq UNION ALL SELECT 2 AS seq) c
    ORDER BY e.emp_name, contact;
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 23:42:28