mysql菜鸟教程
11.2 内连接(INNER JOIN)
在上一节我们了解了连接查询的基本概念,本节将深入探讨最常用的一种连接方式——内连接(INNER JOIN)。内连接返回两个表中满足连接条件的所有行,就像取两个集合的交集。
一、什么是内连接?
内连接只返回两个表中都有匹配的记录。如果某张表的记录在另一张表中找不到对应项,则该记录不会出现在结果中。
用数学中的集合概念来理解:
表A 和 表B 做内连接,结果 = A ∩ B(交集)
只有匹配上的行才会被保留
二、基本语法
SELECT 列名 FROM 表1 INNER JOIN 表2 ON 表1.列 = 表2.列;
也可以省略 INNER,直接写 JOIN,默认就是内连接:
SELECT 列名 FROM 表1 JOIN 表2 ON 表1.列 = 表2.列;
如果连接条件中涉及的列名在两个表中相同,可以使用 USING 简化:
SELECT 列名 FROM 表1 JOIN 表2 USING(共同列名);
三、基础示例:学生与班级
沿用上一节的 students 和 classes 表:
students(学生表)
classes(班级表)
内连接查询:显示有班级的学生及其班级名称
SELECT s.name, c.class_name FROM students s INNER JOIN classes c ON s.class_id = c.class_id;
结果:
注意:学生“赵六”的 class_id 为 NULL,在班级表中没有匹配,所以没有出现在结果中。这正是内连接的特点——只保留匹配的行。
使用 USING 简化
由于连接列在两个表中都叫 class_id,可以简写:
SELECT s.name, c.class_name FROM students s JOIN classes c USING(class_id);
四、内连接与 WHERE 连接的对比
在老式语法中,内连接可以用 WHERE 条件实现:
SELECT s.name, c.class_name FROM students s, classes c WHERE s.class_id = c.class_id;
这种写法虽然结果一样,但有两大缺点:
容易忘记 WHERE 条件,导致笛卡尔积(结果行数爆炸)
连接条件和筛选条件混在一起,可读性差
因此,强烈推荐使用显式的 INNER JOIN 语法。
五、多表内连接
内连接不仅限于两张表,可以连续连接多张表。例如,我们有一个包含成绩的 scores 表:
scores(成绩表)
现在要查询每位有成绩的学生的姓名、班级以及成绩,需要连接三张表:
SELECT s.name, c.class_name, sc.course_name, sc.score FROM students s JOIN classes c ON s.class_id = c.class_id JOIN scores sc ON s.student_id = sc.student_id;
执行逻辑:
先将 students 与 classes 内连接,得到有班级的学生信息。
再将结果与 scores 内连接,得到这些学生的成绩记录。
最终结果只包含既有班级又有成绩的学生(因为内连接层层筛选)。
六、ON 与 WHERE 的先后顺序
在连接查询中,ON 指定连接条件,WHERE 指定结果筛选条件。逻辑上,数据库会先执行连接(根据 ON 生成中间结果),然后再应用 WHERE 过滤。
例如,我们只想查看“计算机1班”的学生成绩:
SELECT s.name, c.class_name, sc.course_name, sc.score FROM students s JOIN classes c ON s.class_id = c.class_id JOIN scores sc ON s.student_id = sc.student_id WHERE c.class_name = '计算机1班';
这里先用 ON 连接三张表,然后 WHERE 过滤班级名称。
如果误将过滤条件写在 ON 中,会得到不同的结果:
SELECT s.name, c.class_name, sc.course_name, sc.score FROM students s JOIN classes c ON s.class_id = c.class_id AND c.class_name = '计算机1班' JOIN scores sc ON s.student_id = sc.student_id;
这样会先按班级名称过滤 classes 表(只保留计算机1班),然后再与学生和成绩表连接。最终结果与之前相同,但逻辑不同。不过性能上可能差不多,但推荐将连接条件放在 ON 中,筛选条件放在 WHERE 中,以保持清晰。
七、内连接的注意事项
NULL 值不参与匹配:因为 NULL 表示未知,任何值与 NULL 比较都是 UNKNOWN,所以不会匹配。上述例子中 class_id 为 NULL 的学生被排除。
连接条件必须明确:务必确保 ON 中的列在两个表中都有对应的值(或者通过外键约束保证)。
重复行问题:如果连接条件不唯一,可能导致结果行数膨胀。例如,如果一个学生有多个成绩(如数学、英语),连接后会出现多行。这是正常的,但需要确认是否符合业务预期。
性能优化:
为连接列(如 class_id、student_id)建立索引。
尽量先用 WHERE 过滤再连接(优化器通常会自行优化,但明确过滤有助于提升效率)。
避免不必要的连接。
八、综合练习
假设我们有如下三张表:
users(用户ID、用户名)
orders(订单ID、用户ID、订单日期)
order_items(订单ID、商品名称、数量、单价)
请用内连接查询出所有有订单的用户及其订单详情。
参考答案:
SELECT u.username, o.order_id, o.order_date, oi.product_name, oi.quantity, oi.unit_price FROM users u JOIN orders o ON u.user_id = o.user_id JOIN order_items oi ON o.order_id = oi.order_id ORDER BY u.username, o.order_date;
九、小结
内连接是日常开发中使用频率最高的连接类型,它帮助我们高效地从多个相关表中提取整合后的数据。

发表评论
所有评论