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

SQL 5.7.37中如何扩展UNION语句合并5个及以上同结构同主键的表?

扩展UNION语句合并多表并基于Title去重的方案

针对你用SQL 5.7.37合并多表且基于Title(唯一索引)去重的需求,我整理了几种和你原有逻辑兼容且扩展性强的方案,帮你轻松处理5个及以上表的合并:

方案1:延续你原有的递进式NOT EXISTS逻辑

这个方案完全沿用你之前双表合并的思路,逐个添加后续表中未出现过的Title行,确保先出现的表中的数据被优先保留(比如Table1的Chad会被保留,Table2/4的Chad会被过滤)。以合并Table1到Table4为例,语句如下:

CREATE TABLE table5 AS
SELECT * FROM table1
UNION ALL
-- 只取Table2中Title不在Table1里的行
SELECT * FROM table2 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.Title = table2.Title)
UNION ALL
-- 只取Table3中Title不在Table1和Table2里的行
SELECT * FROM table3 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.Title = table3.Title)
  AND NOT EXISTS (SELECT 1 FROM table2 WHERE table2.Title = table3.Title)
UNION ALL
-- 只取Table4中Title不在前三个表里的行
SELECT * FROM table4 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.Title = table4.Title)
  AND NOT EXISTS (SELECT 1 FROM table2 WHERE table2.Title = table4.Title)
  AND NOT EXISTS (SELECT 1 FROM table3 WHERE table3.Title = table4.Title);

如果要加第5个表,只需要在后面追加一段类似的UNION ALL,检查前面所有表的Title即可。这个逻辑很直观,和你原来的代码风格一致,SQL 5.7完全支持。

方案2:用UNION自动去重(仅限整行完全重复的场景)

如果你的场景中,相同Title对应的所有列内容都完全一致(比如Table2和Table4里的Chris行完全一样),那可以直接用UNION代替UNION ALL,因为UNION会自动去掉整行重复的记录:

CREATE TABLE table5 AS
SELECT * FROM table1
UNION
SELECT * FROM table2
UNION
SELECT * FROM table3
UNION
SELECT * FROM table4;

⚠️ 注意:UNION是基于所有列去重的,如果存在Title相同但DESC或URL不同的行,UNION会保留这些行,这不符合你的需求。所以这个方案只适合相同Title的行完全一致的情况。

方案3:窗口函数去重(扩展性最好的方案)

SQL 5.7.22及以上版本支持窗口函数,这个方案更简洁,不管多少个表,只需要在内部的UNION ALL里追加表即可。核心思路是先把所有表的行合并,然后为每个Title标记行号,只保留每个Title的第一行:

CREATE TABLE table5 AS
SELECT ID, Title, `DESC`, URL
FROM (
    SELECT *,
           -- 按Title分组,给每个组的行标记序号
           ROW_NUMBER() OVER (PARTITION BY Title ORDER BY (SELECT 0)) AS rn
    FROM (
        SELECT * FROM table1
        UNION ALL
        SELECT * FROM table2
        UNION ALL
        SELECT * FROM table3
        UNION ALL
        SELECT * FROM table4
    ) AS all_merged_tables
) AS ranked_tables
-- 只保留每个Title的第一行
WHERE rn = 1;

这里的ORDER BY (SELECT 0)是让数据库随机选每个Title的一行,如果想优先保留更早的表中的行(比如优先Table1,然后Table2),可以修改排序逻辑,给每个表加个优先级标记:

CREATE TABLE table5 AS
SELECT ID, Title, `DESC`, URL
FROM (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY Title ORDER BY table_priority) AS rn
    FROM (
        SELECT *, 1 AS table_priority FROM table1
        UNION ALL
        SELECT *, 2 AS table_priority FROM table2
        UNION ALL
        SELECT *, 3 AS table_priority FROM table3
        UNION ALL
        SELECT *, 4 AS table_priority FROM table4
    ) AS all_merged_tables
) AS ranked_tables
WHERE rn = 1;

这样每个Title会优先保留优先级数字小的表中的行,完全匹配你原来的逻辑。

额外提醒:关于自增ID的问题

你的原表中ID是自增主键,但合并后的Table5里的ID可能会重复(比如Table1和Table2都有ID=1)。如果需要Table5的ID也是自增唯一的,建议创建表时重新定义ID:

CREATE TABLE table5 (
    ID INT AUTO_INCREMENT PRIMARY KEY,
    Title VARCHAR(255) UNIQUE,
    `DESC` TEXT,
    URL VARCHAR(255)
) AS
-- 这里只选需要的字段,不选原表的ID,让新表自动生成
SELECT Title, `DESC`, URL
FROM (...); -- 这里放上面任意一种方案的子查询

这样新表的ID会从1开始自动递增,不会有重复问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 18:22:26