MySQL 8.0-- join过滤条件放on和where中的区别

总结放前面:

  • 代码run运行顺序
FROM子句
JOIN ON条款
WHERE子句
GROUP BY子句
HAVING子句
SELECT子句
ORDER BY子句
LIMIT条款
  • 在多表联接查询时,on先于where运行。

  • on条件生成笛卡尔积临时表,不论on后面的条件是什么,left join将保全左表的所有记录,right join将保全右表的所有记录。
  • where是对join on之后生成的大表进行过滤,注意这时表联合的操作已经运算完了,where对整表进行过滤。
  • 在inner join的情况下,过滤条件在on条件和where条件中,作用效果是一致的
  • 在left join及right join的情况下,过滤条件在on条件和where条件,作用效果相差很大
  • 本文示例中,提到了不等于 !=将自动过滤 对应空值null的记录

 

1. 语法及运行顺序
   语法顺序

​​​​​​SELECT <字段列表>
FROM <左表>
<连接方式>INNER|LEFT|RIGHT JOIN <右表>
ON <连接条件>
WHERE <过滤条件>
GROUP BY <分组字段>
HAVING <包含条件>
ORDER BY <排序方式>
LIMIT <限制行数>

 执行顺序

FROM子句
JOIN ON条款
WHERE子句
GROUP BY子句
HAVING子句
SELECT子句
ORDER BY子句
LIMIT条款

在多表联接查询时,on先于where运行。on条件生成笛卡尔积临时表,不论on后面的条件是什么,都会返回left join左侧的记录或者right join右侧的记录。

where是对生成的临时表进行过滤,这时就没有join联合的意义了,join联合的操作已经运算之后,where对整表进行过滤。

 

2. 新建简单的示例表

create table student
(
	id int not null,
    name varchar(10) not null,
    primary key(id)
);

insert into student (id,name) values
(1,'aaa'),
(2,'bbb'),
(3,'ccc'),
(4,'ddd'),
(5,'eee'),
(6,'fff');

create table score
(
	id int not null,
    score int not null,
    primary key(id)
);

insert into score (id,score) values
(3,77),
(4,88),
(5,99),
(7,100);

student表内容                                                score表

MySQL 8.0-- join过滤条件放on和where中的区别_第1张图片                                      MySQL 8.0-- join过滤条件放on和where中的区别_第2张图片

2.1. inner join 情况下 

select * from student t inner join score c on t.id=c.id;

MySQL 8.0-- join过滤条件放on和where中的区别_第3张图片

加入 on 条件

select * from student t inner join score c on t.id=c.id and t.id!=3 and c.id!=4;

结果:

加入where条件

发现,在inner join情况下,on和where的作用效果一致


2.2. left join 情况下

select * from student t left join score c on t.id=c.id ;

MySQL 8.0-- join过滤条件放on和where中的区别_第4张图片

加入on条件

select * from student t left join score c on t.id=c.id 
and t.id!=3 
and c.id!=4;

MySQL 8.0-- join过滤条件放on和where中的区别_第5张图片

我们会发现,在left join条件下,筛选条件仅仅对右表产生作用。t.id!=3对左表t没有影响。

并且因为join的条件为左右表的id相同(t.id=c.id),t.id!=3 相当于c.id!=3。

所以笛卡尔积中右表对应id为3,4的数据都为null

再来看看如果改为where会产生什么效果

 

加入where条件:

select * from student t left join score c on t.id=c.id 
where t.id!=3 
and c.id!=4;

结果为: 

可以发现,where条件对前面联结的结果进行了过滤,将t=3,c=4的记录过滤掉了。

好奇的是,为什么id为1,2,6的数据也没有了呢?

因为!=会自动将null给过滤掉。这里的c!=4过滤掉了c为null的记录

如果想显示空值数据,需要显式列出:

select * from student t left join score c on t.id=c.id 
where (t.id!=3 and c.id !=4) or c.id is null;

结果为:

MySQL 8.0-- join过滤条件放on和where中的区别_第6张图片

注意:where是对最后的运算结果进行过滤,所以如果将c.id is null 改为t.id is null,结果还是只有id为5的一行记录。

2.3. right join情况下

select * from student t right join score c on t.id=c.id ;

MySQL 8.0-- join过滤条件放on和where中的区别_第7张图片

加入 on条件 

select * from student t right join score c on t.id=c.id 
and  t.id!=3 
and c.id !=4;

MySQL 8.0-- join过滤条件放on和where中的区别_第8张图片

同样的,可以看出右连接时,过滤条件仅对左表产生影响。

on t.id=c.id and  t.id!=3 and c.id !=4 实际效果为过滤了左表中id为3及4的数据,显示为null

加入where条件

select * from student t right join score c on t.id=c.id 
where t.id!=3 
and c.id !=4;

 

 

你可能感兴趣的:(Mysql,Mysql,多表关联)