SQL语句中IN和exists的区别及应用

本文转自:https://www.cnblogs.com/liyasong/p/sql_in_exists.html

  表展示

    首先,查询中涉及到的两个表,一个用户和一个顺序表,具体表的内容如下:

    用户表:

    

    为了表:

    

 

  在

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

    具体的SQL语句如下:

复制代码
1  选择
2      * 
3  FROM 
4      ` 用户`
 5  WHERE 
6      ` 用户 `.ID IN 7          SELECT 
8              ` 顺序 `。USER_ID 
9          FROM 
10              ` 顺序`
 11
复制代码

    这条语句很简单,通过子查询查询的user_id的数据,去匹配用户表中的id然后得到结果。该语句执行结果如下:

    

    它的执行流程是什么样子的呢?让我们一起来看一下。

    首先,在数据库内部,查询子查询,执行如下代码:

        选择
            ` 订单 `。user_id说明
        FROM 
            ` 为了 `

    执行完毕后,得到结果如下:

    

    此时,将查询到的结果和原有的用户表做一个笛卡尔积,结果如下:

    

    此时,再根据我们的user.id IN order.user_id的条件,将结果进行筛选(既比较id列和user_id列的值是否相等,将不相等的删除)。最后,得到两条符合条件的数据。
    

  存在

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

    具体的SQL语句如下:

复制代码
1  选择
2      ` 用户 `。* 
3  FROM 
4      ` 用户`
 5  WHERE 
6      EXISTS 7          SELECT 
8              ` 顺序 `。USER_ID 
9          FROM 
10              ` 顺序`
 11          WHERE 
12              ` 用户 `.ID = ` 顺序 `。user_id说明
13
复制代码

    这条SQL语句的执行结果和上面的中的执行结果是一样的。

    

    但是,不一样的是它们的执行流程完全不一样:

    使用存在关键字进行查询的时候,首先,我们先查询的不是子查询的内容,而是查我们的主查询的表,也就是说,我们先执行的SQL语句是:

     SELECT `user`.* FROM `user` 

    得到的结果如下:

    

    然后,根据表的每一条记录,执行以下语句,依次去判断where后面的条件是否成立:

复制代码
EXISTS (
        SELECT
            `order`.user_id
        FROM
            `order`
        WHERE
            `user`.id = `order`.user_id
    )
复制代码

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

  区别及应用场景

    in and exists的区别:如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用于,反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用存在。其实我们区分在和存在主要是造成了驱动顺序的改变(这是性能变化的关键),如果是存在,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了,另外在时不对NULL进行处理。

    在是把外表和内表作hash连接,而存在是对外表作循环循环,每次循环再对内表进行查询。一直以来认为存在比效率高的说法是不准确的。

  不在和不存在

    如果查询语句使用了不在那么内外表都进行全表扫描,没有用到索引;而不extsts的子查询依然能用到表上的索引。所以无论那个表大,用不存在都比不在快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值