MySQL左外连接where条件包含多表写法

本文通过具体的SQL示例对比了左外连接与内连接的不同,并解释了在某些特定条件下左外连接如何转变成内连接的现象。尤其关注于ON与WHERE子句的使用顺序及其对连接类型的影响。

首先创建两个表

CREATE TABLE `student` (
	`name` VARCHAR (10) DEFAULT NULL,
	`class` INT (11) DEFAULT NULL
)

CREATE TABLE `score` (
  `name` varchar(10) DEFAULT NULL,
  `subject` varchar(10) DEFAULT NULL,
  `scores` int(11) DEFAULT NULL
)

然后分别插入数据
insert into student values('Tom',1);
insert into student values('Jerry', 2);
insert into score values('Tom','Cat',100);
insert into score values('Tom','Cat',99);
insert into score values('Jerry','Mouse',80);

Sql1:
SELECT
	a.`name`,
	a.`class`,
	b.`subject`,
	b.`scores`
FROM
	student a
LEFT OUTER JOIN score b ON a.`name` = b.`name`
WHERE
	(
		a.class in (1,2) and b.`subject` = 'Mouse'
	)

返回的数据并不是left join,反而是inner join的数据
+-------+-------+---------+--------+
| name  | class | subject | scores |
+-------+-------+---------+--------+
| Jerry |     2 | Mouse   |     80 |
+-------+-------+---------+--------+

Sql2:
SELECT
	a.`name`,
	a.`class`,
	b.`subject`,
	b.`scores`
FROM
	student a
LEFT OUTER JOIN score b ON a.`name` = b.`name` and b.`subject` = 'Mouse'
WHERE
	(
		a.class in (1,2) 
	)

这个数据是正常的
+-------+-------+---------+--------+
| name  | class | subject | scores |
+-------+-------+---------+--------+
| Jerry |     2 | Mouse   |     80 |
| Tom   |     1 | NULL    |   NULL |
| Tom   |     1 | NULL    |   NULL |
+-------+-------+---------+--------+

由此可以看出来,当左外链接的时候,如果where里面包含右表的字段,那么左连接就会转变成内连接。这个因为sql执行优先级导致的问题,where的优先级是低于join链接的。
<think> 我们被要求详细解释MySQL查询中的内连接和外连接。 根据提供的引用,我们可以总结如下: 1. 内连接(INNER JOIN): - 只返回两个中连接字段相等的行,即只返回两个的交集部分。 - 有两种写法:显式内连接(使用INNER JOIN关键字)和隐式内连接(在FROM后跟,然后在WHERE中写连接条件)。 - 例如:查询有订单的用户及其订单信息,没有订单的用户就不会显示。 2. 外连接OUTER JOIN): - 外连接分为外连接LEFT JOIN)和右外连接(RIGHT JOIN)。 - 外连接:返回的所有行,以及右中满足连接条件的行。如果右中没有匹配的行,则结果中对应列显示为NULL。 - 右外连接:返回右的所有行,以及中满足连接条件的行。如果中没有匹配的行,则结果中对应列显示为NULL。 3. 自连接(SELF JOIN):其实是一种特殊的内连接或外连接,它是将一个与自身连接。 我们将按照以下结构组织回答: - 内连接:解释概念,给出显式和隐式写法的例子。 - 外连接:分别解释外连接和右外连接,并给出例子。 - 可能还需要说明全外连接(但MySQL不支持,可以通过UNION连接和右连接实现)?但引用中没有提到,所以暂时不提。 注意:引用中提到了自连接,但用户问题只要求内连接和外连接,所以我们重点在内连接和外连接。 我们将使用用户提供的引用中的例子,并适当修改以使其更清晰。 此外,我们还需要注意,在写SQL时,连接条件通常使用ON关键字,而筛选条件使用WHERE。 根据引用[3]和[4]中的例子,我们可以构建自己的示例。 假设我们有两个:员工(emp)和部门(dept)。 - 员工包含:id, name, dept_id(部门ID) - 部门包含:id, name(部门名称) 内连接示例:查询每个员工及其所在部门的名称(只显示有部门的员工) 外连接示例:查询所有部门及其员工(包括没有员工的部门)——这里用右外连接,或者用外连接(以部门) 但注意,引用[4]中有一个查询老王的例子,我们可以借用。 我们分别用显式和隐式写法来写内连接,然后分别写外连接和右外连接。 另外,注意引用[1]中对外连接的解释:外连接相当于查所有数据以及两交集部分。 现在开始组织回答。 </think>### MySQL查询:内连接与外连接详解 #### 一、内连接(INNER JOIN) **概念**:仅返回两个中**匹配条件的交集数据**,不匹配的行会被过滤掉。相当于数学中的集合交集操作。 **语法形式**: 1. **显式内连接**(标准写法) ```sql SELECT 列名 FROM 1 INNER JOIN 2 ON 1.关联字段 = 2.关联字段 [WHERE 筛选条件]; ``` 示例:查询员工及其部门名称(仅显示有部门的员工) ```sql SELECT e.name, d.dname FROM emp e INNER JOIN dept d ON e.dept_id = d.id; ``` 2. **隐式内连接**(传统写法) ```sql SELECT 列名 FROM 1, 2 WHERE 1.关联字段 = 2.关联字段 [AND 筛选条件]; ``` 示例:查询"老王"的部门信息 ```sql SELECT e.id, e.name, d.name FROM emp e, dept d WHERE e.dept_id = d.id AND e.name='老王'; ``` **特点**: - 结果集中只包含关联字段匹配的行 - 未分配部门的员工/无员工的部门不会显示 - 执行效率通常高于外连接[^3] --- #### 二、外连接OUTER JOIN) **概念**:返回主全部数据+从匹配数据,从无匹配时填充`NULL`。分两种类型: 1. **外连接LEFT JOIN)** - 以为主,返回所有行 + 右匹配行 - 语法: ```sql SELECT 列名 FROM LEFT JOIN 右 ON .字段 = 右.字段; ``` 示例:查询所有员工及其部门(含未分配部门的员工) ```sql SELECT e.name, d.dname FROM emp e LEFT JOIN dept d ON e.dept_id = d.id; ``` > 结果包含: > `张三 | 研发部` > `李四 | NULL` ← 未分配部门的员工 2. **右外连接(RIGHT JOIN)** - 以右为主,返回右所有行 + 匹配行 - 语法: ```sql SELECT 列名 FROM RIGHT JOIN 右 ON .字段 = 右.字段; ``` 示例:查询所有部门及其员工(含无员工的部门) ```sql SELECT d.dname, e.name FROM emp e RIGHT JOIN dept d ON e.dept_id = d.id; ``` > 结果包含: > `研发部 | 张三` > `行政部 | NULL` ← 无员工的部门 --- #### 三、核心区别总结 | 特性 | 内连接 | 外连接 | 右外连接 | |--------------|---------------------------|--------------------------|--------------------------| | **主** | 无 | | 右 | | **返回数据** | 仅匹配记录 | 全部+右匹配 | 右全部+匹配 | | **NULL处理** | 不出现NULL列 | 右无匹配时显示NULL | 无匹配时显示NULL | | **应用场景** | 需要严格匹配的场景 | 保留主完整数据 | 保留从完整数据 | > **实际建议**: > 1. 需要完整主数据时用外连接(如统计部门人数需包含0人部门) > 2. 仅需关联数据时用内连接(如订单-商品查询) > 3. 优先使用显式写法(`INNER JOIN/LEFT JOIN`),可读性更强[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值