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

SQL新手求助:能否用Union合并order_id=1的两条差异记录?

解决同order_id多条记录的合并问题

嘿,作为SQL新手碰到这种同订单ID但联系人不同的情况太常见啦,我来给你详细讲讲怎么处理~

首先先纠正你对UNION的小误解:UNION其实是用来合并结构完全相同的数据集,它会自动去重;如果不想去重就用UNION ALL。它并不是用来合并同ID下的不同字段的,你的需求更适合用分组聚合或者特定场景下的自JOIN,下面给你具体的方案:

方法一:分组+字符串聚合(最通用推荐)

因为你的数据里,同order_id的order_location和order_value都是一致的,我们可以把这三个字段作为分组依据,然后用字符串聚合函数把同一个组里的order_contact合并成一个字段。

先给你模拟你的数据表(方便测试):

CREATE TABLE orders (
    order_id INT,
    order_contact VARCHAR(50),
    order_location VARCHAR(50),
    order_value INT
);

INSERT INTO orders VALUES
(1, 'Tom''s Business', '123 Street', 100),
(1, 'John''s Management', '123 Street', 100),
(2, 'Tim''s Business', '543 Avenue', 50),
(3, 'Phil''s Business', '789 Avenue', 50);

不同数据库的写法:

  • MySQL/MariaDB 使用GROUP_CONCAT:
SELECT 
    order_id,
    GROUP_CONCAT(order_contact SEPARATOR ', ') AS combined_contacts,
    order_location,
    order_value
FROM orders
GROUP BY order_id, order_location, order_value;
  • PostgreSQL 使用STRING_AGG:
SELECT 
    order_id,
    STRING_AGG(order_contact, ', ') AS combined_contacts,
    order_location,
    order_value
FROM orders
GROUP BY order_id, order_location, order_value;
  • SQL Server 2017+ 也支持STRING_AGG:
SELECT 
    order_id,
    STRING_AGG(order_contact, ', ') AS combined_contacts,
    order_location,
    order_value
FROM orders
GROUP BY order_id, order_location, order_value;
  • SQL Server 2016及更早版本 可以用STUFF+FOR XML PATH的组合:
SELECT 
    o.order_id,
    STUFF((SELECT ', ' + order_contact 
           FROM orders 
           WHERE order_id = o.order_id 
           FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '') AS combined_contacts,
    o.order_location,
    o.order_value
FROM orders o
GROUP BY o.order_id, o.order_location, o.order_value;

执行后你会得到这样的结果:

order_idcombined_contactsorder_locationorder_value
1Tom's Business, John's Management123 Street100
2Tim's Business543 Avenue50
3Phil's Business789 Avenue50

方法二:自JOIN(仅适合同order_id最多两条记录的场景)

如果你的数据里每个order_id最多只有两条不同的order_contact,可以用自JOIN来合并,但这个方法局限性很大,不推荐用于通用场景:

-- 合并order_id=1的两条记录
SELECT 
    o1.order_id,
    CONCAT(o1.order_contact, ', ', o2.order_contact) AS combined_contacts,
    o1.order_location,
    o1.order_value
FROM orders o1
JOIN orders o2 ON o1.order_id = o2.order_id AND o1.order_contact < o2.order_contact
WHERE o1.order_id = 1

-- 再把其他单独的记录加进来
UNION ALL

SELECT 
    order_id,
    order_contact AS combined_contacts,
    order_location,
    order_value
FROM orders
WHERE order_id NOT IN (1);

这个方法如果遇到同一个order_id有3条及以上记录,会生成重复的组合结果,所以还是方法一更靠谱。

再啰嗦下UNION的正确用法

你之前以为UNION适用于不同结构的数据集,刚好相反:UNION要求两个查询结果的列数、列数据类型必须完全匹配,它的作用是把两个结果集上下拼接起来。比如你有两个订单表orders_2023和orders_2024,结构完全一样,要合并成一个全年的订单列表,就可以用:

SELECT * FROM orders_2023
UNION ALL
SELECT * FROM orders_2024;

用UNION会自动去重(如果有重复的订单记录),UNION ALL则保留所有记录,效率更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:09:43