Mysql 多表关联链接顺序说明

博客介绍了MySQL多表关联查询使用Nested - Loop Join算法,驱动表数据量影响查询效率。指出from后表顺序不决定实际关联顺序,MySQL会选最优顺序,也可通过Optimizer Hints(8.0)指定,还通过实例展示顺序变化及相关指定方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mysql对多表关联查询使用Nested-Loop Join算法,简单总结就是通过驱动表作为入口,一层层的往内部查询,驱动表的数据量对查询效率很关键。

而对驱动表的选择,from后的表顺序并不起决定作用,mysql会根据多重因素选择最优的链接顺序。如果想自行控制链接顺序可以通过Optimizer Hints(mysql 8.0)指定。

使用saklia数据库

1.先通过一个left join的例子说明from后的表顺序对实际执行时的关联顺序不起决定作用的现象

explain 
select a.rental_id, a.rental_date,b.film_id
  from rental a left join inventory b on a.inventory_id = b.inventory_id

在这里插入图片描述
可以看到执行顺序是a>b

2.接下来,我们调换一下表的顺序

explain 
select a.rental_id, a.rental_date,b.film_id
  from inventory b left join rental a on a.inventory_id = b.inventory_id

在这里插入图片描述
从explain输出结果看,b确实到前面去了,变成了b>a

3.还没结束接着看,我们带上a的一个条件

explain
select a.rental_id, a.rental_date,b.film_id
  from inventory b left join rental a on a.inventory_id = b.inventory_id
 where  a.rental_date >= '2005-01-19 02:18:51';

在这里插入图片描述
看到顺序又变成了a>b,此sql并未改变from表的顺序,只是增加了a的过滤条件
4.如果就是想将b放到第一个驱动表的位置,可以通过Optimizer Hints的JOIN_PREFIX指定

explain
 select /*+JOIN_PREFIX(b) */  a.rental_id, a.rental_date,b.film_id
   from inventory b left join rental a on a.inventory_id = b.inventory_id
 where  a.rental_date >= '2005-01-19 02:18:51';

在这里插入图片描述
不过JOIN_PREFIX只有mysql8.0才有,5.7并没有。除了JOIN_PREFIX还有JOIN_FIXED_ORDER、JOIN_ORDER、JOIN_SUFFIX用来指定表链接顺序

更多Optimizer Hints信息可到官网查看https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html

<think>嗯,用户这次的问题很明确,是关于MySQL连接操作的指南。从系统指令看,用户需要技术性强的中文回答,且要严格遵循LaTeX格式要求。用户可能正在学习SQL连接查询,或是工作中遇到了关联的实际问题。 用户提供的引用材料很全面,涵盖了INNER JOIN、LEFT JOIN、RIGHT JOIN和FULL JOIN的概念对比。不过引用[3]提到MySQL不支持FULL OUTER JOIN,这点需要特别说明。用户的核心诉求应该是掌握不同连接类型的适用场景和语法细节。 考虑到用户可能是数据库初学者,我决定从基础概念讲起,用格对比四种连接方式,再配以实际SQL示例。特别注意要强调MySQL不支持FULL JOIN这个易错点,并给出替代方案。用户可能还会关心性能优化,所以需要补充ON和WHERE子句的区别说明。 在示例设计上,采用部门-员工的经典模型最直观。第一个示例用INNER JOIN展示基本匹配,第二个用LEFT JOIN突出保留主数据的特性,第三个用RIGHT JOIN时准备提醒实际开发中较少使用。对于FULL JOIN的模拟方案,UNION ALL的写法要确保正确性。 最后生成的问题要覆盖进阶内容:性能优化和实际应用场景能帮助用户深化理解,而FULL JOIN的替代方案则是MySQL特有的技术点。用户如果已经看到JOIN语法,很可能下一步会想了解执行计划优化。 需要特别注意LaTeX格式的严格性:行内公式如$t1.column$必须用美元符号包裹,所有SQL关键字大写保持规范。引用标记要准确对应到提供的参考材料,特别是FULL JOIN的限制说明要标注[^2]。</think>以下是 MySQL 连接操作的详细指南,涵盖 `INNER JOIN`、`LEFT JOIN`、`RIGHT JOIN` 及 `FULL JOIN` 的模拟实现: --- ### **一、连接类型详解与语法** #### **1. INNER JOIN(内连接)** - **作用**:仅返回两中**匹配成功**的行。 - **语法**: ```sql SELECT 列名 FROM 1 INNER JOIN 2 ON 1.关联列 = 2.关联列; ``` - **示例**:查询员工及其所属部门(仅显示有部门的员工) ```sql SELECT employees.name, departments.dept_name FROM employees INNER JOIN departments ON employees.dept_id = departments.id; ``` #### **2. LEFT JOIN(左外连接)** - **作用**:返回**左全部行** + **右匹配行**(无匹配时右字段为 `NULL`)。 - **语法**: ```sql SELECT 列名 FROM 1 LEFT JOIN 2 ON 1.关联列 = 2.关联列; ``` - **示例**:查询所有员工及其部门(包括未分配部门的员工) ```sql SELECT employees.name, departments.dept_name FROM employees LEFT JOIN departments ON employees.dept_id = departments.id; ``` #### **3. RIGHT JOIN(右外连接)** - **作用**:返回**右全部行** + **左匹配行**(无匹配时左字段为 `NULL`)。 - **语法**: ```sql SELECT 列名 FROM 1 RIGHT JOIN 2 ON 1.关联列 = 2.关联列; ``` - **示例**:查询所有部门及其员工(包括无员工的部门) ```sql SELECT employees.name, departments.dept_name FROM employees RIGHT JOIN departments ON employees.dept_id = departments.id; ``` #### **4. FULL OUTER JOIN(全外连接)** - **作用**:返回两的**并集**(匹配行 + 左独有行 + 右独有行)。 ⚠️ **MySQL 原生不支持**,需用 `UNION` 模拟: - **语法**: ```sql SELECT 列名 FROM 1 LEFT JOIN 2 ON 关联条件 UNION SELECT 列名 FROM 1 RIGHT JOIN 2 ON 关联条件; ``` - **示例**:查询所有员工和部门的组合(包括未分配部门的员工和空部门) ```sql SELECT employees.name, departments.dept_name FROM employees LEFT JOIN departments ON employees.dept_id = departments.id UNION SELECT employees.name, departments.dept_name FROM employees RIGHT JOIN departments ON employees.dept_id = departments.id; ``` --- ### **二、核心对比** | 连接类型 | 返回结果 | 是否保留未匹配行 | MySQL支持 | |----------------|-----------------------------------|------------------------|-----------| | `INNER JOIN` | 两交集 | ❌ 不保留 | ✅ | | `LEFT JOIN` | 左全集 + 右匹配行 | ✅ 保留左未匹配行 | ✅ | | `RIGHT JOIN` | 右全集 + 左匹配行 | ✅ 保留右未匹配行 | ✅ | | `FULL JOIN` | 左全集 + 右全集(去重) | ✅ 保留所有未匹配行 | ❌(需模拟)| --- ### **三、关键注意事项** 1. **关联条件** - 使用 `ON` 指定连接条件(如 `ON t1.id = t2.foreign_id`),避免漏写导致笛卡尔积。 - **筛选条件**应放在 `WHERE` 而非 `ON` 中(除非需保留未匹配行)[^3]。 2. **性能优化** - 为关联列创建索引:`ALTER TABLE 名 ADD INDEX(列名);` - 避免 `SELECT *`,仅查询必要字段。 3. **连接顺序** 按数据过滤性安排顺序:优先连接能缩小结果集的。 --- ### **四、应用场景建议** - ✅ **INNER JOIN**:需精确匹配时(如订单详情关联商品信息)。 - ✅ **LEFT JOIN**:以左为主体的分析(如统计用户行为,即使未发生行为)。 - ✅ **RIGHT JOIN**:以右为主体的报(如展示所有产品库存,即使未售出)。 - ✅ **UNION 模拟 FULL JOIN**:数据对比或合并(如员工-部门全量关系分析)[^2]。 --- **示例结构参考** ```sql CREATE TABLE departments ( id INT PRIMARY KEY, dept_name VARCHAR(50) ); CREATE TABLE employees ( id INT PRIMARY KEY, name VARCHAR(50), dept_id INT, FOREIGN KEY (dept_id) REFERENCES departments(id) ); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值