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

SQL分组后单人多课程单行显示的执行原理及分步解析

课程查询SQL的两个问题解答

现有如下Courses表结构及初始化数据:

CREATE TABLE Courses
(name   VARCHAR(32), 
 course VARCHAR(32), 
 PRIMARY KEY(name, course));

INSERT INTO Courses VALUES('Tom', 'SQL');
INSERT INTO Courses VALUES('Tom', 'UNIX');
INSERT INTO Courses VALUES('Jack', 'SQL');
INSERT INTO Courses VALUES('Mike', 'SQL');
INSERT INTO Courses VALUES('Mike', 'Java');
INSERT INTO Courses VALUES('Jane', 'UNIX');
INSERT INTO Courses VALUES('Mary', 'SQL');

执行以下SQL可得到每个人的课程分布(每行对应一个人,各课程列显示是否选修):

select name,
(select 'o' from Courses where name = c.name and course = 'SQL')as SQL,
(select 'o' from Courses where name = c.name and course = 'UNIX')as UNIX,
(select 'o' from Courses where name = c.name and course = 'Java')as Java
from Courses c
group by name

查询结果如下(每个人一行,对应课程列有值则表示选修该课程,无值则为NULL):

nameSQLUNIXJava
TomooNULL
JackoNULLNULL
MikeoNULLo
JaneNULLoNULL
MaryoNULLNULL

一、如何实现将每个人的所有课程合并显示在同一行?

根据需求不同,有两种常用实现思路:

思路1:行转列展示(分课程列显示)

这种是把每个人的课程拆分为多列,标记是否选修,有两种实现方式:

  • 子查询方式:即题目中给出的SQL,为每个课程单独写关联子查询,判断当前用户是否选修该课程,返回'o'或NULL,最后通过GROUP BY name合并同一用户的记录为一行。
  • 条件聚合方式(更高效):用CASE WHEN结合聚合函数(如MAX)实现,避免多次扫描表,性能更优,代码示例:
SELECT 
    name,
    MAX(CASE WHEN course = 'SQL' THEN 'o' END) AS SQL,
    MAX(CASE WHEN course = 'UNIX' THEN 'o' END) AS UNIX,
    MAX(CASE WHEN course = 'Java' THEN 'o' END) AS Java
FROM Courses
GROUP BY name;

思路2:合并为单个字符串字段

如果需求是把一个人的所有课程放在同一个字段里,用字符串聚合函数(不同数据库语法略有差异):

  • MySQL:
SELECT name, GROUP_CONCAT(course SEPARATOR ', ') AS courses
FROM Courses
GROUP BY name;
  • PostgreSQL/SQL Server:
SELECT name, STRING_AGG(course, ', ') AS courses
FROM Courses
GROUP BY name;

结果示例:

namecourses
TomSQL, UNIX
JackSQL
MikeSQL, Java
JaneUNIX
MarySQL

二、给定SQL的具体分步执行逻辑

  1. 获取基础数据:FROM Courses c 扫描整个Courses表,得到所有name+course的原始记录。
  2. 按用户分组:GROUP BY name 对原始记录按name分组,每个用户仅保留一行数据(保证每个name唯一)。
  3. 执行关联子查询:对每个分组后的用户,分别执行三个子查询:
    • 第一个子查询:在Courses表中查找当前用户是否选修SQL,找到则返回'o',否则返回NULL。
    • 第二个子查询:同理,判断当前用户是否选修UNIX,返回对应标记或NULL。
    • 第三个子查询:判断当前用户是否选修Java,返回对应标记或NULL。
  4. 组装最终结果:将name与三个子查询的结果拼接成一行,每个用户对应一行,得到最终的行转列结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:40:35