MySQL 多表联查
多表联查核心就是JOIN(连接),分为:INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN(MySQL 不支持,用 union 模拟),还有隐式连接(逗号写法)。
准备两张示例表
-- 用户表 user CREATE TABLE user( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), age INT ); -- 订单表 order CREATE TABLE `order`( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT, -- 外键,关联user.id order_name VARCHAR(50) );1、内连接 INNER JOIN(最常用)
只返回两张表匹配上的数据,两边都有才出结果
语法:
SELECT 字段 FROM 表A INNER JOIN 表B ON 表A.关联字段 = 表B.关联字段;示例:查询用户以及对应的订单
SELECT u.name, o.order_name FROM user u INNER JOIN `order` o ON u.id = o.user_id;别名:
u代表 user,o代表 order
隐式内连接(逗号写法,等价 inner join)
SELECT u.name, o.order_name FROM user u,`order` o WHERE u.id = o.user_id;⚠️不要忘记 where 条件,否则会产生笛卡尔积(数据爆炸)
2、左连接 LEFT JOIN(LEFT OUTER JOIN)
以左边表为主,左表全部数据都展示;右表匹配不到,字段为 NULL
SELECT u.name, o.order_name FROM user u LEFT JOIN `order` o ON u.id = o.user_id;场景:查询所有用户,包含没有下单的用户。
如果只想查左表有、右表没有的数据(没有订单的用户):
SELECT u.name FROM user u LEFT JOIN `order` o ON u.id = o.user_id WHERE o.id IS NULL;3、右连接 RIGHT JOIN
以右边表为主,右表全部数据,左表匹配不到则 NULL
SELECT u.name, o.order_name FROM user u RIGHT JOIN `order` o ON u.id = o.user_id;4、全连接 FULL JOIN
MySQL没有 FULL JOIN 关键字,想要左右全部数据,用
LEFT JOIN UNION RIGHT JOIN
SELECT u.name, o.order_name FROM user u LEFT JOIN `order` o ON u.id=o.user_id UNION SELECT u.name, o.order_name FROM user u RIGHT JOIN `order` o ON u.id=o.user_id;5、三张及以上表联查
多张表就继续JOIN ... ON往后拼接
SELECT u.name,o.order_name,g.goods_name FROM user u LEFT JOIN `order` o ON u.id = o.user_id LEFT JOIN goods g ON o.goods_id = g.id;6、子查询实现多表(不是 JOIN,另一种方案)
-- where中子查询 SELECT * FROM user WHERE id IN (SELECT user_id FROM `order`); -- from子查询(派生表) SELECT * FROM (SELECT * FROM user WHERE age>18) t1 LEFT JOIN `order` o ON t1.id = o.user_id;7、关键注意事项
- ON 和 WHERE 的区别
ON:join 连接时做匹配条件WHERE:连接完成之后,对结果集过滤
left join 中,条件写 on 和 where 结果完全不一样!
示例坑点:
-- ❌错误:left join后where过滤order表,会把null数据过滤掉,退化成内连接 SELECT u.name,o.order_name FROM user u LEFT JOIN `order` o ON u.id=o.user_id WHERE o.order_name='手机'; -- ✅正确,把条件放on SELECT u.name,o.order_name FROM user u LEFT JOIN `order` o ON u.id=o.user_id AND o.order_name='手机';- 避免笛卡尔积:join 必须写 on 关联条件
- 字段重名,必须指定表别名:
u.id,不能只写id - 性能:关联字段建议建立索引(外键字段加索引,联查速度提升巨大)
快速选型记忆
表格
| 连接类型 | 作用 |
|---|---|
| INNER JOIN | 两边匹配的数据 |
| LEFT JOIN | 左边全部,右边匹配 |
| RIGHT JOIN | 右边全部,左边匹配 |
| UNION | 合并结果集 |