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