> 文档中心 > SQL中,in和exists详解+案例

SQL中,in和exists详解+案例

SQL中,in和exists详解+案例

    • 1. 案例表结构
    • 2. 什么是in
      • 2.1 执行逻辑
    • 3. 什么是exists
      • 3.1 执行逻辑

1. 案例表结构

  1. 一张人员表:user
    SQL中,in和exists详解+案例

  2. 一张地区表:area
    SQL中,in和exists详解+案例

  3. 一张中间表:user_area
    SQL中,in和exists详解+案例

以当前初始数据表示我们知道:张三和李四两个人的地区是”成都“,王五的地区是”湖南“。

2. 什么是in

in 操作符允许我们在 where子句中规定多个值。我们在开发中最常用的就是in。

现在如果我们有一个需求:用一条sql查出地区属于”成都“的人员的名字。

SELECTuser_name FROMUSER WHEREid IN (SELECTua.u_id FROMuser_area uaINNER JOIN area a ON ua.a_id = a.id AND a.area_name = '成都') 

这条sql包含了一个子查询,先从中间表查出满足条件的用户的id,再把这些查出来的id作为查询条件去user表中做in条件查询。所以sql简化出来就是这样的:

select user_name from user where id in (1,2) 

2.1 执行逻辑

select * from A
where id in(select id from B)

in()只执行一次,它查出B表中的所有id字段并缓存起来之后,检查A表的id是否与B表中的id相等,如果等则
将A表的记录加入结果集中,直到遍历完A表的所有记录。

如果用伪代码来表示,可以这样理解:

List resultSet=[];Array A=(select * from A);Array B=(select id from B);for(int i=0;i<A.length;i++) {   for(int j=0;j<B.length;j++) {      if(A[i].id==B[j].id) {  resultSet.add(A[i]);  break;      }   }}return resultSet;

可以看出,当B表数据较大时不适合使用in(),因为它会B表数据全部遍历一次.
结论:in()适合B表比A表数据小的情况

3. 什么是exists

exists运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False。
(指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样的。匹配上就将结果放入结果集中。)
所以,使用exists的话,子查询实际上不会返回任何数据结果,只会返回true和false。如果我们用exists来完成之前的需求,改怎么做呢?
用一条sql查出地区属于”成都“的人员的名字。

SELECTuser_name FROMUSER AS a WHEREEXISTS (SELECTb.u_id FROMuser_area bINNER JOIN area c ON b.a_id = c.id AND c.area_name = '成都' WHEREa.id = b.u_id #重要的一行);

3.1 执行逻辑

select a.* from A a
where exists(select 1 from B b where a.id=b.id)

exists()会执行A.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要,重要的是结果集中是否有记录,如果有则返回true,没有则返回false.

如果用伪代码来表示,可以这样理解:

List resultSet=[];Array A=(select * from A)for(int i=0;i<A.length;i++) {   if(exists(A[i].id) {    //执行select 1 from B b where b.id=a.id是否有记录返回resultSet.add(A[i]);   }}return resultSet;

简单点一句话就是:会循环A表length次,每次会把A表的数据带到B表进行匹配,匹配上的话就加入结果集。

当B表比A表数据大时适合使用exists(),因为它没有那么遍历操作,只需要再执行一次查询就行.
结论:in()适合B表比A表数据大的情况