导读:本期聚焦于小伙伴创作的《SQL视图中如何处理多对多关系的扁平化?使用GROUP_CONCAT或STRING_AGG可行吗》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《SQL视图中如何处理多对多关系的扁平化?使用GROUP_CONCAT或STRING_AGG可行吗》有用,将其分享出去将是对创作者最好的鼓励。

多对多关系与扁平化需求

在数据库设计中,多对多关系通常通过三张表实现:两张实体表加一张中间关联表。比如学生表和课程表,一个学生可以选多门课程,一门课程也可以被多个学生选择,二者通过学生课程关联表建立联系。这种结构在存储时非常规范,但在查询时如果需要将某个学生选择的所有课程名称合并展示成一条记录,就需要对多对多关系进行扁平化处理。

SQL视图中如何处理多对多关系的扁平化?使用GROUP_CONCAT或STRING_AGG可行吗

传统查询的问题

如果不做扁平化处理,查询学生对应的课程会返回多条记录,比如学生A选了数学、语文、英语三门课,查询结果会有三行,每行对应一门课程。这种结果在部分业务场景中不符合需求,比如前端列表需要一行展示学生的所有课程信息,就需要将多行合并成一行。

使用GROUP_CONCAT实现扁平化(MySQL、SQLite)

GROUP_CONCAT是MySQL和SQLite支持的字符串聚合函数,它可以将分组后的多个值按照指定分隔符拼接成一个字符串,非常适合处理多对多关系的扁平化。

基础表结构示例

我们首先创建三张测试表,模拟学生和课程的关联关系:

-- 学生表
CREATE TABLE student (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL
);

-- 课程表
CREATE TABLE course (
    id INT PRIMARY KEY AUTO_INCREMENT,
    course_name VARCHAR(50) NOT NULL
);

-- 学生课程关联表
CREATE TABLE student_course (
    student_id INT,
    course_id INT,
    PRIMARY KEY (student_id, course_id),
    FOREIGN KEY (student_id) REFERENCES student(id),
    FOREIGN KEY (course_id) REFERENCES course(id)
);

创建包含扁平化结果的视图

我们可以通过GROUP_CONCAT函数创建视图,将每个学生的课程名称拼接成逗号分隔的字符串:

CREATE VIEW student_course_flat AS
SELECT 
    s.id AS student_id,
    s.name AS student_name,
    GROUP_CONCAT(c.course_name SEPARATOR ',') AS course_list
FROM student s
LEFT JOIN student_course sc ON s.id = sc.student_id
LEFT JOIN course c ON sc.course_id = c.id
GROUP BY s.id, s.name;

上述视图中,我们通过LEFT JOIN关联三张表,然后按照学生ID和姓名分组,使用GROUP_CONCAT将同一个学生的所有课程名称拼接起来,默认分隔符是逗号,也可以通过SEPARATOR参数自定义分隔符。

查询视图结果

直接查询视图可以得到扁平化后的结果:

SELECT * FROM student_course_flat;

如果学生A的ID是1,选择了数学、语文、英语三门课,查询结果中course_list字段的值会是“数学,语文,英语”。

使用STRING_AGG实现扁平化(PostgreSQL、SQL Server)

STRING_AGG是PostgreSQL和SQL Server支持的字符串聚合函数,功能和GROUP_CONCAT类似,语法上略有差异。

PostgreSQL中的实现

在PostgreSQL中,创建同样的视图可以使用以下语句:

CREATE VIEW student_course_flat AS
SELECT 
    s.id AS student_id,
    s.name AS student_name,
    STRING_AGG(c.course_name, ',') AS course_list
FROM student s
LEFT JOIN student_course sc ON s.id = sc.student_id
LEFT JOIN course c ON sc.course_id = c.id
GROUP BY s.id, s.name;

STRING_AGG的第一个参数是要拼接的字段,第二个参数是分隔符,用法和GROUP_CONCAT的SEPARATOR参数类似。

SQL Server中的实现

SQL Server从2017版本开始支持STRING_AGG函数,使用方式和PostgreSQL基本一致:

CREATE VIEW student_course_flat AS
SELECT 
    s.id AS student_id,
    s.name AS student_name,
    STRING_AGG(c.course_name, ',') AS course_list
FROM student s
LEFT JOIN student_course sc ON s.id = sc.student_id
LEFT JOIN course c ON sc.course_id = c.id
GROUP BY s.id, s.name;

两种函数的注意事项

  • 如果分组后没有匹配的关联记录,GROUP_CONCAT和STRING_AGG都会返回NULL,如果需要返回空字符串,可以使用COALESCE函数处理,比如COALESCE(STRING_AGG(c.course_name, ','), '')。
  • GROUP_CONCAT在MySQL中有长度限制,默认是1024字符,如果拼接的字符串过长,可以通过调整group_concat_max_len参数修改限制。
  • 两种函数都支持排序,比如GROUP_CONCAT(c.course_name ORDER BY c.course_name SEPARATOR ',')可以按照课程名称升序拼接结果。

适用场景总结

当需要在SQL视图中处理多对多关系的扁平化时,GROUP_CONCAT和STRING_AGG是非常合适的选择。如果是MySQL或SQLite数据库,优先使用GROUP_CONCAT;如果是PostgreSQL或SQL Server数据库,优先使用STRING_AGG。这种方式可以将复杂的多表关联查询逻辑封装到视图中,简化上层业务的查询操作,同时提升查询效率。

SQL视图多对多关系GROUP_CONCATSTRING_AGG关系扁平化修改时间:2026-06-25 18:48:17

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。