在前面的学习里,我们已经熟悉了内连接的基本概念。但是在实际的数据库操作中,只有一个内连接是远远不够的,我们经常会遇到更复杂的连接需求。 所以接下来,我们将深入探讨其他几种重要的连接类型,包括外连接、交叉连接和自然连接,这些技巧将让你的 SQL 查询更加灵活。

在之前使用内连接的例子中,我们总是假设两个表之间的连接条件能够找到匹配的记录。但在现实场景中,这种假设并不总是成立。 假设你正在管理一个在线教育平台的数据库。你有一个「学生表」和一个「课程报名表」。如果你想查看所有学生的信息,包括那些还没有报名任何课程的学生,普通的内连接就无法满足这个需求了。
让我们通过一个具体的例子来理解这个问题。假设我们有以下数据:
-- 学生表
SELECT student_id, student_name FROM students;-- 课程报名表
SELECT student_id, course_name FROM enrollments;注意到学生「王五」(student_id = 3)还没有报名任何课程。如果我们使用内连接:
SELECT s.student_name, e.course_name
FROM students s INNER JOIN enrollments e
ON s.student_id = e.student_id;结果中就不会包含王五的信息,因为在报名表中找不到匹配的记录。
外连接的核心价值在于保留某一个表的所有记录,即使在另一个表中找不到匹配的数据。这在数据分析和报表生成中非常重要。
左外连接(LEFT OUTER JOIN)是一种关系型数据库中的连接操作,其主要作用是返回左表(查询语句中 FROM 子句指定的第一个表)中的所有记录, 即使这些记录在右表(JOIN 子句指定的表)中没有对应的匹配行。对于那些在右表中找不到匹配的左表记录, 查询结果中右表的所有字段会自动以 NULL 进行填充。
这样可以确保左表的数据完整性,常用于需要展示主表全部信息、并补充关联表数据的场景。 例如在学生与课程报名的关系中,左外连接可以帮助我们查找所有学生及其报名情况, 即使某些学生尚未报名任何课程,也能在结果中体现出来。需要注意的是,LEFT OUTER JOIN 通常可以简写为 LEFT JOIN,二者在语义和功能上完全等价。 继续使用我们的教育平台例子:
SELECT s.student_name, e.course_name
FROM students s LEFT OUTER JOIN enrollments e
ON s.student_id = e.student_id;通过使用左外连接(LEFT OUTER JOIN),我们能够查询出所有学生的信息,即使某些学生还没有报名任何课程。
例如,在上面的结果中,学生「王五」虽然没有报名,但依然会出现在结果中,course_name 字段为 NULL。
这种查询方式非常适合用于生成全面的学生报告,确保不会遗漏任何学生的数据。
举个实际应用场景:如果你想统计每个学生已经报名的课程数量,无论他是否报名,都能在统计结果中体现出来。 这样可以帮助学校或教育平台了解哪些学生还没有参与课程,便于后续的跟进和管理。
SELECT s.student_name, COUNT(e.course_name) as course_count
FROM students s LEFT OUTER JOIN enrollments e
ON s.student_id = e.student_id
GROUP BY s.student_name;右外连接(RIGHT OUTER JOIN)是一种关系型数据库中的连接操作,其核心作用是返回右表(即在 JOIN 子句中指定的第二个表)中的所有记录, 无论这些记录在左表(FROM 子句指定的第一个表)中是否存在匹配的数据。对于那些在左表中找不到匹配的右表记录,查询结果中左表的所有字段会自动以 NULL 进行填充。
这种连接方式非常适用于需要完整展示参考表(如课程、产品、部门等)信息的场景,即使某些参考表中的数据尚未与主表产生关联,也能在结果中体现出来。 右外连接常用于统计分析、报表生成等业务需求,确保右表的数据不会被遗漏。
需要注意的是,RIGHT OUTER JOIN 通常可以简写为 RIGHT JOIN,二者在语义和功能上完全等价。 与左外连接(LEFT OUTER JOIN)相比,右外连接只是将左右表的角色进行了对调,选择哪种方式主要取决于实际业务需求和查询的可读性。 假设我们现在有一个「课程表」,记录了所有可选的课程:
-- 课程表
SELECT course_id, course_name FROM courses;如果我们想查看所有课程的报名情况,包括那些还没有学生报名的课程:
SELECT c.course_name, COUNT(e.student_id) as enrollment_count
FROM enrollments e RIGHT OUTER JOIN courses c
ON e.course_name = c.course_name
GROUP BY c.course_name;这样我们就能看出「数据分析」课程还没有学生报名,我们可以选择删除这门课程,或者加强引导学生报这门课。
记住,LEFT OUTER JOIN 和 RIGHT OUTER JOIN 本质上是可以互换的,关键在于你把哪个表放在左边,哪个表放在右边。 选择哪种方式主要取决于你的查询逻辑和代码的可读性。
在实际项目开发中,数据往往分布在多个表中,我们经常需要将三个、四个甚至更多的表进行关联查询,以获得完整的业务信息。
外连接(OUTER JOIN)在这种多表场景下尤为重要,因为它能够确保主表的所有数据都被保留,即使某些关联表中没有对应的数据,也不会导致主表信息丢失,
而是以 NULL 进行填充。
让我们以一个典型的教育平台为例,详细说明多表外连接的实际应用。假设我们有如下三张表:
在实际业务中,我们可能需要生成一份详尽的学生报告,内容包括每个学生的基本信息、所报名的课程,以及对应的付费记录。
由于有些学生可能还没有报名课程,或者已经报名但尚未缴费,因此我们需要用外连接来保证所有学生都能出现在最终结果中,缺失的信息以 NULL 显示。
下面是具体的业务需求和分析:
student_id 进行左外连接,这样即使学生没有报名课程,学生信息也不会丢失。student_id 进行左外连接,这样即使学生没有付费记录,前面的信息也会被保留。通过这种多表外连接的方式,我们可以全面地展示每个学生的所有相关信息:
SELECT
s.student_name,
s.email,
e.course_name,
p.amount as payment_amount
FROM students s
LEFT OUTER JOIN enrollments e ON s.student_id = e.student_id
LEFT OUTER JOIN payments p ON s.student_id = p.student_id这个查询会返回所有学生的信息,即使某些学生没有报名课程或者没有付费记录,对应的字段会显示为 NULL。
如果我们想要一个更清晰的报告,可以使用之前学过的子查询来重新组织这个复杂的连接:
SELECT
student_with_courses.student_name,
student_with_courses.course_name,
p.amount as payment_amount
FROM (
SELECT s.student_id, s.student_name, e.course_name
FROM students s
LEFT OUTER JOIN enrollments e ON s.student_id = e.
使用子查询可以让复杂的多表连接更容易理解和维护。每个子查询处理一个特定的连接关系,最终组合成完整的结果。
自外连接(Self-Join with Outer Join)是一种特殊的外连接操作,其核心思想是将同一个表作为连接的两端,通过外连接的方式将其自身进行关联。
自外连接常用于处理具有层级结构或父子关系的数据场景,例如组织架构、分类树、菜单结构等。
在这些场景中,表中的某些字段(如 manager_id、parent_id)引用了自身的主键,从而形成递归或分层的数据关系。

通过自外连接,我们不仅可以查询每个元素与其直接上级(或下级)的对应关系,还能确保即使某些元素没有上级(如顶层管理者)或没有下级(如叶子节点), 这些元素的信息也不会在结果中丢失。这对于完整展示层级结构、生成组织报表或实现递归查询具有重要意义。
自外连接通常通过为同一张表设置不同的别名,并使用外连接(如 LEFT OUTER JOIN 或 RIGHT OUTER JOIN)将其自身关联起来,
结合适当的连接条件(如 e.manager_id = m.emp_id),实现对层级关系的全面分析和展示。
考虑一个企业员工管理系统,其中员工表记录了每个员工及其上级的信息:
-- 员工表
SELECT emp_id, emp_name, manager_id FROM employees;如果我们使用内连接来查看员工和他们的上级:
SELECT e.emp_name as employee, m.emp_name as manager
FROM employees e INNER JOIN employees m
ON e.manager_id = m.emp_id;使用内连接时,只有那些在两边表中都能找到匹配关系的记录才会被返回。因此,在员工和上级的自连接查询中,只有有上级的员工(即 manager_id 不为 NULL 的员工)才会出现在结果中。
像张总这样的最高级别管理者,由于他的 manager_id 为 NULL,在员工表中找不到对应的上级记录,所以不会被包含在查询结果里。
这意味着所有没有上级的顶层管理者信息都会被遗漏,无法在结果中体现。
使用左外连接可以解决这个问题:
SELECT e.emp_name as employee, m.emp_name as manager
FROM employees e LEFT OUTER JOIN employees m
ON e.manager_id = m.emp_id;现在我们可以看到完整的组织架构,包括最高级别的管理者。 如果我们想查看每个管理者及其下属,可以使用右外连接:
SELECT e.emp_name as employee, m.emp_name as manager
FROM employees e RIGHT OUTER JOIN employees m
ON e.manager_id = m.emp_id;这种查询对于生成组织架构图和计算管理层级非常有用。
交叉连接(CROSS JOIN)会产生两个表的笛卡尔积,也就是说,第一个表的每一行都会与第二个表的每一行进行组合。 虽然这听起来可能会产生大量的数据,但在某些特定场景下,交叉连接却是非常有用的工具。
让我们通过一个具体的例子来理解交叉连接。假设你正在为一个餐厅管理系统设计菜单组合:
-- 主食表
SELECT main_dish FROM main_dishes;-- 汤品表
SELECT soup FROM soups;如果你想生成所有可能的主食和汤品组合:
SELECT m.main_dish, s.soup
FROM main_dishes m CROSS JOIN soups s;这样我们就得到了 6 种不同的套餐组合(3 种主食 × 2 种汤品)。
交叉连接在数据分析中经常用于生成测试数据、创建时间序列表格,或者进行复杂的数学计算。虽然不常用,但在特定场景下非常强大。
交叉连接的一个经典应用是生成连续的日期序列。假设我们需要生成 2024 年全年的日期列表,但数据库中没有现成的日期表。 我们可以通过交叉连接来巧妙地解决这个问题:
-- 首先创建数字表
SELECT
(ones.num + tens.num + hundreds.num) as day_offset
FROM
(SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION
SELECT 4 UNION SELECT 5 UNION SELECT
这个查询会生成从 0 到 399 的所有数字。然后我们可以将这些数字加到 2024 年 1 月 1 日上:
SELECT
DATE_ADD('2024-01-01', INTERVAL day_offset DAY) as date_2024
FROM (
SELECT (ones.num + tens.num + hundreds.num) as day_offset
FROM
(SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
这样我们就能得到 2024 年的所有日期,包括闰年的 2 月 29 日。
这种技巧在需要生成报表时特别有用,比如你想统计每天的交易数量,即使某些天没有交易记录,也要在报表中显示 0:
SELECT
dates.date_2024,
COUNT(orders.order_id) as daily_orders
FROM (
-- 生成2024年所有日期的子查询
SELECT DATE_ADD('2024-01-01', INTERVAL day_offset DAY) as date_2024
FROM (
SELECT (ones.num + tens.num + hundreds.num)
这个查询结合了交叉连接和外连接的技巧,能够生成一个完整的 2024 年日报表,即使某些日期没有订单,也会显示为 0。
自然连接(NATURAL JOIN)是一种特殊的 SQL 连接方式,它会自动识别并使用两个表中所有同名的列作为连接条件,实现表之间的关联。 虽然这种方式在语法上简洁高效,但在实际应用中需要谨慎使用,以避免因表结构变更或同名但语义不同的列导致数据结果异常。
让我们通过一个例子来理解自然连接的工作原理。假设我们有以下两个表:
-- 学生表
SELECT student_id, student_name, class_id FROM students;-- 班级表
SELECT class_id, class_name, teacher_name FROM classes;由于两个表都有 class_id 列,我们可以使用自然连接:
SELECT student_name, class_name, teacher_name
FROM students NATURAL JOIN classes;数据库会自动识别 class_id 作为连接条件,相当于:
SELECT student_name, class_name, teacher_name
FROM students s INNER JOIN classes c
ON s.class_id = c.class_id;尽管自然连接在语法上简洁高效,但其存在显著的风险:一旦表结构发生变更,查询结果可能会因隐式连接条件的变化而产生不可预期的错误。
假设我们现在需要在学生表中添加一个 teacher_id 字段来记录班主任:
-- 修改后的学生表
SELECT student_id, student_name, class_id, teacher_id FROM students;如果班级表也有 teacher_id 字段:
-- 修改后的班级表
SELECT class_id, class_name, teacher_name, teacher_id FROM classes;现在,当我们再次执行自然连接时:
SELECT student_name, class_name, teacher_name
FROM students NATURAL JOIN classes;数据库会同时使用 class_id 和 teacher_id 作为连接条件,这可能不是我们想要的结果。如果某个学生的班主任与班级的任课老师不一致,该学生就不会出现在结果中。
自然连接的最大问题是它的行为依赖于表结构。当表结构发生变化时,查询的行为也会发生变化,这可能导致难以发现的错误。因此,在生产环境中应该避免使用自然连接。
更好的做法是显式地指定连接条件:
SELECT s.student_name, c.class_name, c.teacher_name
FROM students s INNER JOIN classes c
ON s.class_id = c.class_id;这样,即使表结构发生任何的变化,查询的逻辑仍然清晰明确。
假设我们有一个教育管理系统,包含以下表结构:
-- 学生表
CREATE TABLE students (
student_id INT PRIMARY KEY,
student_name VARCHAR(50),
department_id INT,
enrollment_year INT
);
-- 部门表
CREATE TABLE departments (
department_id INT PRIMARY KEY,
department_name VARCHAR(100),
head_teacher_id INT
);
我们拥有以下的测试数据:
-- 插入学生数据
INSERT INTO students VALUES
(1, '张三', 1, 2022),
(2, '李四', 1, 2022),
(3, '王五', 2, 2023),
(4, '赵六', 2, 2023),
(5,
SELECT s.student_name, c.course_name, e.enrollment_date
FROM students s
LEFT OUTER JOIN enrollments e ON s.student_id = e.student_id
LEFT OUTER JOIN courses c ON e.course_id = c.course_id
ORDER BY s.student_name;SELECT c.course_name, COUNT(e.student_id) as student_count
FROM courses c
LEFT OUTER JOIN enrollments e ON c.course_id = e.course_id
GROUP BY c.course_name, c.course_id
ORDER BY student_count DESC;
SELECT s.student_name, COUNT(e.course_id) as course_count
FROM students s
LEFT OUTER JOIN enrollments e ON s.student_id = e.student_id
GROUP BY s.student_name, s.student_id
ORDER BY course_count DESC;
SELECT t.teacher_name, d.department_name
FROM teachers t
RIGHT OUTER JOIN departments d ON t.department_id = d.department_id;SELECT t.teacher_name, d.department_name
FROM teachers t
RIGHT OUTER JOIN departments d ON t.department_id = d.department_idSELECT c.course_name, d.department_name
FROM courses c
RIGHT OUTER JOIN departments d ON c.department_id = d.department_id;+-----------------+--------------------+
| course_name | department_name |
+-----------------+--------------------+
| Python编程 | 计算机科学系 |
|
SELECT c.course_name
FROM courses c
LEFT OUTER JOIN enrollments e ON c.course_id = e.course_id
WHERE e.enrollment_id IS NULL;+--------------+
| course_name |
+--------------+
| Python编程 |
+--------------+SELECT s.student_name, c.course_name, g.score
FROM students s
LEFT OUTER JOIN enrollments e ON s.student_id = e.student_id
LEFT OUTER JOIN courses c ON e.course_id = c.course_id
LEFT OUTER JOIN grades g ON e.enrollment_id = g
SELECT
s.student_name,
d.department_name,
c.course_name,
g.score,
CASE
WHEN g.score >= 90 THEN '优秀'
WHEN g.score >= 80 THEN '良好'
WHEN g.score >= 70 THEN
SELECT
c.course_name,
COUNT(DISTINCT e.student_id) as enrolled_students,
AVG(g.score) as avg_score,
MIN(g.score) as min_score,
MAX(g.score) as max_score
FROM courses c
LEFT OUTER JOIN
SELECT t.teacher_name, head.head_teacher_name
FROM teachers t
LEFT OUTER JOIN (
SELECT d.department_id, t2.teacher_name as head_teacher_name
FROM departments d
LEFT OUTER JOIN teachers t2 ON d.head_teacher_id = t2.teacher_id
) head ON t.department_id =
SELECT
t1.teacher_name as teacher1,
t2.teacher_name as teacher2,
d.department_name
FROM teachers t1
CROSS JOIN teachers t2
LEFT OUTER JOIN departments d ON t1.department_id = d.department_id
WHERE t1.teacher_id < t2.teacher_id
AND t1.department_id
SELECT
s1.student_name as student,
s2.student_name as classmate,
s1.enrollment_year
FROM students s1
CROSS JOIN students s2
WHERE s1.student_id < s2.student_id
AND s1.enrollment_year = s2.enrollment_year
ORDER BY s1.enrollment_year, s1SELECT s.student_name, c.course_name
FROM students s
CROSS JOIN courses c
ORDER BY s.student_name, c.course_name;+--------------+-----------------+
| student_name | course_name |
+--------------+-----------------+
| 孙七 | Python编程 |
|
SELECT
days.day_name,
slots.time_slot
FROM (
SELECT 'Monday' as day_name UNION ALL
SELECT 'Tuesday' UNION ALL
SELECT 'Wednesday' UNION ALL
SELECT 'Thursday' UNION ALL
SELECT 'Friday' UNION ALL
SELECT 'Saturday' UNION ALL
SELECT 'Sunday'
) days
CROSS JOIN (
SELECT
SELECT t.teacher_name, c.course_name, d.department_name
FROM teachers t
CROSS JOIN courses c
LEFT OUTER JOIN departments d ON t.department_id = d.department_id
ORDER BY t.teacher_name, c.course_name;+--------------+-----------------+--------------------+
SELECT
s.student_name,
d.department_name as student_dept,
c.course_name,
c.credit_hours,
g.score,
t.teacher_name as course_teacher,
dt.department_name as teacher_dept,
e.semester
FROM students s
LEFT OUTER JOIN departments d
SELECT
s.student_name,
COALESCE(AVG(g.score), 0) as avg_score,
COUNT(g.score) as courses_taken
FROM students s
LEFT OUTER JOIN enrollments e ON s.student_id = e.student_id
LEFT OUTER JOIN grades g ON e
SELECT
d.department_name,
COUNT(DISTINCT t.teacher_id) as teacher_count,
COUNT(DISTINCT c.course_id) as course_count,
COUNT(DISTINCT e.student_id) as enrolled_students,
AVG(g.score) as avg_department_score,
COUNT
+--------------+-----------------+-----------------+
| student_name | course_name | enrollment_date |
+--------------+-----------------+-----------------+
| 孙七 | 数据结构 | 2023-09-01 |
| 张三 | 数据结构 | 2023-09-01 |
| 张三 | 数据库设计 | 2023-09-01 |
| 李四 | 高等数学 | 2023-09-01 |
| 李四 | 数据库设计 | 2023-09-01 |
| 王五 | 高等数学 | 2023-09-01 |
| 赵六 | 量子物理 | 2023-09-01 |
| 赵六 | 线性代数 | 2023-09-01 |
+--------------+-----------------+-----------------++--------------+-----------------+-------+
| student_name | course_name | score |
+--------------+-----------------+-------+
| 孙七 | 数据结构 | NULL |
| 张三 | 数据库设计 | 85.50 |
| 张三 | 数据结构 | 92.00 |
| 李四 | 数据库设计 | 78.50 |
| 李四 | 高等数学 | 88.00 |
| 王五 | 高等数学 | 95.50 |
| 赵六 | 线性代数 | 82.00 |
| 赵六 | 量子物理 | 76.50 |
+--------------+-----------------+-------++--------------+--------------------+-----------------+-------+-------------+
| student_name | department_name | course_name | score | grade_level |
+--------------+--------------------+-----------------+-------+-------------+
| 孙七 | 计算机科学系 | 数据结构 | NULL | 不及格 |
| 张三 | 计算机科学系 | 数据库设计 | 85.50 | 良好 |
| 张三 | 计算机科学系 | 数据结构 | 92.00 | 优秀 |
| 李四 | 计算机科学系 | 数据库设计 | 78.50 | 中等 |
| 李四 | 计算机科学系 | 高等数学 | 88.00 | 良好 |
| 王五 | 数学系 | 高等数学 | 95.50 | 优秀 |
| 赵六 | 数学系 | 线性代数 | 82.00 | 良好 |
| 赵六 | 数学系 | 量子物理 | 76.50 | 中等 |
+--------------+--------------------+-----------------+-------+-------------++-----------------+-------------------+-----------+-----------+-----------+
| course_name | enrolled_students | avg_score | min_score | max_score |
+-----------------+-------------------+-----------+-----------+-----------+
| 数据结构 | 2 | 92.000000 | 92.00 | 92.00 |
| 高等数学 | 2 | 91.750000 | 88.00 | 95.50 |
| 数据库设计 | 2 | 82.000000 | 78.50 | 85.50 |
| 线性代数 | 1 | 82.000000 | 82.00 | 82.00 |
| 量子物理 | 1 | 76.500000 | 76.50 | 76.50 |
| Python编程 | 0 | NULL | NULL | NULL |
+-----------------+-------------------+-----------+-----------+-----------++--------------+-------------------+
| teacher_name | head_teacher_name |
+--------------+-------------------+
| 刘老师 | 刘老师 |
| 王老师 | 王老师 |
| 赵老师 | 陈老师 |
| 陈老师 | 陈老师 |
+--------------+-------------------+
+-----------+-----------+--------------------+
| teacher1 | teacher2 | department_name |
+-----------+-----------+--------------------+
| 陈老师 | 赵老师 | 计算机科学系 |
+-----------+-----------+--------------------++---------+-----------+-----------------+
| student | classmate | enrollment_year |
+---------+-----------+-----------------+
| 张三 | 李四 | 2022 |
| 张三 | 孙七 | 2022 |
| 李四 | 孙七 | 2022 |
| 王五 | 赵六 | 2023 |
+---------+-----------+-----------------++-----------+-------------+
| day_name | time_slot |
+-----------+-------------+
| Monday | 10:40-12:10 |
| Monday | 14:00-15:30 |
| Monday | 15:40-17:10 |
| Monday | 9:00-10:30 |
| Tuesday | 10:40-12:10 |
| Tuesday | 14:00-15:30 |
| Tuesday | 15:40-17:10 |
| Tuesday | 9:00-10:30 |
| Wednesday | 10:40-12:10 |
| Wednesday | 14:00-15:30 |
| Wednesday | 15:40-17:10 |
| Wednesday | 9:00-10:30 |
| Thursday | 10:40-12:10 |
| Thursday | 14:00-15:30 |
| Thursday | 15:40-17:10 |
| Thursday | 9:00-10:30 |
| Friday | 10:40-12:10 |
| Friday | 14:00-15:30 |
| Friday | 15:40-17:10 |
| Friday | 9:00-10:30 |
| Saturday | 10:40-12:10 |
| Saturday | 14:00-15:30 |
| Saturday | 15:40-17:10 |
| Saturday | 9:00-10:30 |
| Sunday | 10:40-12:10 |
| Sunday | 14:00-15:30 |
| Sunday | 15:40-17:10 |
| Sunday | 9:00-10:30 |
+-----------+-------------++--------------+--------------------+-----------------+--------------+-------+----------------+--------------------+------------+
| student_name | student_dept | course_name | credit_hours | score | course_teacher | teacher_dept | semester |
+--------------+--------------------+-----------------+--------------+-------+----------------+--------------------+------------+
| 孙七 | 计算机科学系 | 数据结构 | 4 | NULL | 陈老师 | 计算机科学系 | 2023秋季 |
| 张三 | 计算机科学系 | 数据库设计 | 3 | 85.50 | 陈老师 | 计算机科学系 | 2023秋季 |
| 张三 | 计算机科学系 | 数据结构 | 4 | 92.00 | 陈老师 | 计算机科学系 | 2023秋季 |
| 李四 | 计算机科学系 | 数据库设计 | 3 | 78.50 | 陈老师 | 计算机科学系 | 2023秋季 |
| 李四 | 计算机科学系 | 高等数学 | 5 | 88.00 | 王老师 | 数学系 | 2023秋季 |
| 王五 | 数学系 | 高等数学 | 5 | 95.50 | 王老师 | 数学系 | 2023秋季 |
| 赵六 | 数学系 | 线性代数 | 4 | 82.00 | 王老师 | 数学系 | 2023秋季 |
| 赵六 | 数学系 | 量子物理 | 4 | 76.50 | 刘老师 | 物理系 | 2023秋季 |
+--------------+--------------------+-----------------+--------------+-------+----------------+--------------------+------------++--------------+-----------+---------------+
| student_name | avg_score | courses_taken |
+--------------+-----------+---------------+
| 王五 | 95.500000 | 1 |
| 张三 | 88.750000 | 2 |
| 李四 | 83.250000 | 2 |
| 赵六 | 79.250000 | 2 |
| 孙七 | 0.000000 | 0 |
+--------------+-----------+---------------++--------------------+---------------+--------------+-------------------+----------------------+------------------+
| department_name | teacher_count | course_count | enrolled_students | avg_department_score | passing_students |
+--------------------+---------------+--------------+-------------------+----------------------+------------------+
| 数学系 | 1 | 2 | 3 | 88.500000 | 3 |
| 计算机科学系 | 2 | 3 | 3 | 85.333333 | 2 |
| 物理系 | 1 | 1 | 1 | 76.500000 | 1 |
+--------------------+---------------+--------------+-------------------+----------------------+------------------+