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

SQL多表查询去重并合并指定列数据的实现方法咨询

嘿,我明白你的问题了——你通过JOIN和UNION拉取多表数据后,出现了重复ID的行,想要把同一ID对应的Exams内容合并到一行里,而且没法用createDate去重,因为日期也重复对吧?

你原来的查询用了DISTINCT加UNION ALL,但DISTINCT是针对整行数据去重的,只要某一行的任何一列和其他行不一样,就会被保留,所以没法解决同一ID但Exams不同的重复问题。要实现合并Exams的需求,核心思路是先把所有需要的数据整合到一起,再按ID分组,用字符串聚合函数把Exams列合并起来。

下面分不同数据库给你具体的解决方案:

针对SQL Server的写法

先用CTE把UNION ALL后的所有数据整合,再按ID和其他非聚合列分组,用STRING_AGG合并Exams:

WITH CombinedData AS (
    -- 第一部分:calsses与documents的关联数据
    SELECT 
        table1.ID,
        table1.ClassName, -- 替换成table1实际的列名,不要用*
        table1.Teacher,
        table2.Date,
        table2.DocumentName,
        table1.Exams AS ExamContent -- 单独提取Exams,方便后续聚合
    FROM calsses table1 
    INNER JOIN documents table2 ON table1.ID = table2.ID
    UNION ALL
    -- 第二部分:exams与documents的关联数据
    SELECT 
        table3.ID,
        table3.ClassName, -- 必须和上面的列顺序、数据类型完全一致
        table3.Teacher,
        table2.Date,
        table2.DocumentName,
        table3.Exams AS ExamContent
    FROM exams table3 
    INNER JOIN documents table2 ON table3.ID = table2.ID
)
SELECT 
    ID,
    ClassName,
    Teacher,
    Date,
    DocumentName,
    STRING_AGG(ExamContent, ', ') AS Exams -- 用逗号分隔多个考试内容,可自定义分隔符
FROM CombinedData
GROUP BY ID, ClassName, Teacher, Date, DocumentName -- 所有非聚合列都要明确列出
ORDER BY Date DESC; -- 保持你原有的排序需求

针对MySQL的写法

MySQL用GROUP_CONCAT函数实现字符串聚合,用子查询替代CTE:

SELECT 
    ID,
    ClassName,
    Teacher,
    Date,
    DocumentName,
    GROUP_CONCAT(ExamContent SEPARATOR ', ') AS Exams
FROM (
    SELECT 
        table1.ID,
        table1.ClassName,
        table1.Teacher,
        table2.Date,
        table2.DocumentName,
        table1.Exams AS ExamContent
    FROM calsses table1 
    INNER JOIN documents table2 ON table1.ID = table2.ID
    UNION ALL
    SELECT 
        table3.ID,
        table3.ClassName,
        table3.Teacher,
        table2.Date,
        table2.DocumentName,
        table3.Exams AS ExamContent
    FROM exams table3 
    INNER JOIN documents table2 ON table3.ID = table2.ID
) AS CombinedData
GROUP BY ID, ClassName, Teacher, Date, DocumentName
ORDER BY Date DESC;

针对PostgreSQL的写法

PostgreSQL同样支持STRING_AGG,写法和SQL Server的CTE方式一致:

WITH CombinedData AS (
    SELECT 
        table1.ID,
        table1.ClassName,
        table1.Teacher,
        table2.Date,
        table2.DocumentName,
        table1.Exams AS ExamContent
    FROM calsses table1 
    INNER JOIN documents table2 ON table1.ID = table2.ID
    UNION ALL
    SELECT 
        table3.ID,
        table3.ClassName,
        table3.Teacher,
        table2.Date,
        table2.DocumentName,
        table3.Exams AS ExamContent
    FROM exams table3 
    INNER JOIN documents table2 ON table3.ID = table2.ID
)
SELECT 
    ID,
    ClassName,
    Teacher,
    Date,
    DocumentName,
    STRING_AGG(ExamContent, ', ') AS Exams
FROM CombinedData
GROUP BY ID, ClassName, Teacher, Date, DocumentName
ORDER BY Date DESC;

几个关键注意点:

  • 务必把table1.*、table3.*换成具体的列名,不能用通配符*,因为GROUP BY要求明确列出所有非聚合的列,规范写法必须列全。
  • 保证UNION ALL前后两部分的列数、顺序、数据类型完全一致,否则会出现数据类型不匹配的错误。
  • 如果同一ID下的其他列(比如ClassName、Teacher)存在不同的值,GROUP BY后会把这些不同的组合分成多行。如果不符合需求,可以用MAX(ClassName)、MIN(Teacher)这类聚合函数统一这些列的值。
  • 分隔符可以按需修改,比如换成'; '或者' | '都可以。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:51:52