【SQL 】in 和 exists 的区别

in 和 exists 都是关联查询的关键字,准备工作,先创建 2 张表格,如 user(用户表)、order(订单表)

user 表:

在这里插入图片描述

order 表:

在这里插入图片描述

in 的查询如下:

确定给定的值是否与子查询或列表中的值相匹配。
in 在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快。
SQL 如下:

SELECT
	*
FROM
	USER
WHERE
	user_id IN (
		SELECT
			`order`.order_user_id
		FROM
			`order`
	)

这条 SQL 很简单,通过子查询查到的 order 表中的 order_user_id 的数据,去匹配 user 表中的 user_id ,然后得到结果。
该语句执行结果如下:
在这里插入图片描述
看下 SQL 的执行流程是什么
首先,在数据库内部,先执行子查询
SQL 如下:

SELECT
	`order`.order_user_id
FROM
	`order`

该语句执行结果如下:
在这里插入图片描述
此时,将查询到的结果和原来的 user 表做一个笛卡尔积。
结果如下:
在这里插入图片描述
笛卡尔积:是指两个或多个表中的所有可能的行组合。在 SQL 中,可以使用 CROSS JOIN 来获取所有行组合。
例如:有 table1 表和 table2 表,可以使用如下 SQL :

SELECT
	*
FROM
	table1
CROSS JOIN table2

再根据 user_id in order.order_user_id 的条件,将结果进行筛选(比较 user_id 列和 order_user_id 列的值是否相等,将不相等的删除),最后,得到相应的结果。

exists 的查询如下:

指定一个子查询,检测行是否存在。遍历循环外表,然后看外表的记录有没有和内表的数据一样的,匹配上就将结果放入集中。
SQL 如下:

SELECT
	`user`.*
FROM
	`user`
WHERE
	EXISTS (
		SELECT
			`order`.order_user_id
		FROM
			`order`
		WHERE
			`user`.user_id = `order`.order_user_id
	)

该语句执行结果如下:
在这里插入图片描述
可以看出,exists 和 in 的执行结果是一样的。
看下 SQL 的执行流程是什么
使用 exists 关键字进行查询的时候,首先区别于 in 查询,先查询的不是子查询的内容,而是先查的是主查询的表。
也就是,先执行的 SQL 如下:

SELECT
	`user`.*
FROM
	`user`

其结果如下:
在这里插入图片描述
然后,根据结果中的每一条记录,执行以下的 SQL ,依次去判断 where 后面的条件是否成立:

EXISTS (
		SELECT
			`order`.order_user_id
		FROM
			`order`
		WHERE
			`user`.user_id = `order`.order_user_id
	)

如果成立则返回 true,将执行的结果集保留,不成立则返回 false。则删除该行,最后将得到的结果集返回。

in 和 exists 的区别

如果子查询的结果集记录较少,主查询中的表较大且又有索引时应该用 in, 反之如果外层的主查询记录较少,子查询中的表较大,又有索引时使用 exists。其实我们区分 in 和 exists 主要是造成了驱动顺序的改变(这是性能变化的关键),如果是 exists,那么以外层表为驱动表,先被访问,如果是 in ,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了 ,另外 in 时不对 null 进行处理。
in 是把外表和内表作 hash 连接,而 exists 是对外表作 loop 循环,每次 loop 循环再对内表进行查询。一直以来认为 exists 比 in 效率高的说法是不准确的。

摘录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值