zoukankan      html  css  js  c++  java
  • SQL深入 :exist 和 in 的用法和区别

     in 适用于 外大内小, 而exists适用于 外小内大!

    假设如下应用:
    两张表——用户表TDefUser(userid,address,phone)和消费表TAccConsume(userid,time,amount),需要查消费超过5000的用户记录。
    用exists:
    select * from TDefUser
    where exists (select 1 from TAccConsume where TDefUser.userid=TAccConsume.userid and TAccConsume.amount>5000)
    用in:
    select * from TDefUser
    where userid in (select userid from TAccConsume where TAccConsume.amount>5000)

    通常情况下采用exists要比in效率高。

    exists()后面的子查询被称做相关子查询他是不返回列表的值的.只是返回一个ture或false的结果(这也是为什么子查询里是"select 1"的原因,换成"select 6"完全一样,当然也可以select字段,但是明显效率低些)
    其运行方式是先运行主查询一次 再去子查询里查询与其对应的结果如果是ture则输出,反之则不输出.再根据主查询中的每一行去子查询里去查询.

    in()后面的子查询是返回结果集的,换句话说执行次序和exists()不一样.子查询先产生结果集,然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出. 

    比如用户表TDefUser(userid,address,phone),消费表TAccConsume(userid,time,amount)数据如下:

    消费表聚集索引是userid,time
    数据(注意因为有聚集索引,实际存储也是按以下次序的)
    1   2006-1-1  200
    1   2006-1-2  300
    1   2006-1-2  500
    1   2006-1-3  2000
    1   2006-1-3  2000
    1   2006-1-4  400
    1   2006-1-5  500
    2   2006-1-1  200
    2   2006-1-2  300
    2   2006-1-2  500
    2   2006-1-3  2000
    2   2006-1-3  6000
    2   2006-1-4  400
    2   2006-1-5  8000
    3   2006-1-1  7000
    3   2006-1-2  30000
    3   2006-1-2  50000
    3   2006-1-3  20000

    语句:
    select * from TDefUser
    where exists (select 1 from TAccConsume where TDefUser.userid=TAccConsume.userid and TAccConsume.amount>5000)

    对于userid=1,需要找所有记录,才返回false,与第二个语句的效率差不多
    对于userid=2,找到2006-1-3的记录,就返回true,比第而个语句的效率高
    对于userid=3,第一条记录就返回true,比第二个语句的效率高

    语句
    select * from TDefUser
    where userid in (select userid from TAccConsume where TAccConsume.amount>5000)

    返回空记录集
    2
    2
    3
    3
    3
    3

    再判断

    语句
    select * from TDefUser
    where userid in (select userid from TAccConsume where userid=TDefUser.userid and amount>5000)

    对于userid=1,需要找所有记录,返回空记录集,比较判断
    对于userid=2,需要找所有记录,返回记录集
    2
    2
    ,比较判断
    对于userid=3需要找所有记录,返回记录集
    3
    3
    3
    3
    ,比较判断

    表中如果没有聚集索引,对exists每个userid查找的条数都不同,但都是<=第三个语句需要扫描的条数,极端的(比如>5000的都是在最后)与第三个语句效率相似,一般的比第二个语句快,所以说,“一般”exists比in效率高

     

     
    ----------------------------------------------------------------------------------
     
    附上一篇觉得正确的文章,欢迎探讨:

    in 和 exists也是很好区别的.

    in 是一个集合运算符.

    a in {a,c,d,s,d....}

    这个运算中,前面是一个元素,后面是一个集合,集合中的元素类型是和前面的元素一样的.

    而exists是一个存在判断,如果后面的查询中有结果,则exists为真,否则为假.

    in 运算用在语句中,它后面带的select 一定是选一个字段,而不是select *.

    比如说你要判断某班是否存在一个名为"小明"的学生,你可以用in 运算:

    "小明" in (select sname from student)

    这样(select sname from student) 返回的是一个全班姓名的集合,in用于判断"小明"是否为此集合中的一个数据;

    同时,你也可以用exists语句:

    exists (select * from student where sname="小明")

    这两个涵数是差不多的, 但是由于优化方案的不同, 通常NOT EXISTS要比NOT IN 要快, 因为NOT EXISTS可以使用结合算法而NOT IN 就不行了,而EXISTS则不如IN快, 因为这时候IN可能更多的使用结合算法.

    select * from 表A where exists(select * from 表B where 表B.id=表A.id)

    这句相当于

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


    对于表A的每一条数据,都执行select * from 表B where 表B.id=表A.id的存在性判断,如果表B中存在表A当前行相同的id,则exists为真,该行显示,否则不显示

    exits适合内小外大的查询,in适合内大外小的查询

    IN
    确定给定的值是否与子查询或列表中的值相匹配。

    EXISTS
    指定一个子查询,检测行的存在。

    比较使用 EXISTS 和 IN 的查询

    这个例子比较了两个语义类似的查询。第一个查询使用 EXISTS 而第二个查询使用 IN。注意两个查询返回相同的信息。

    USE pubs
    GO
    SELECT DISTINCT pub_name
    FROM publishers
    WHERE EXISTS
    (SELECT *
    FROM titles
    WHERE pub_id = publishers.pub_id
    AND type = 'business')
    GO

    -- Or, using the IN clause:

    USE pubs
    GO
    SELECT distinct pub_name
    FROM publishers
    WHERE pub_id IN
    (SELECT pub_id
    FROM titles
    WHERE type = 'business')
    GO



    下面是任一查询的结果集:

    pub_name
    ----------------------------------------
    Algodata Infosystems
    New Moon Books

    (2 row(s) affected)

    exits 相当于存在量词:表示集合存在,也就是集合不为空只作用一个集合.例如 exist P 表示P不空时为真; not exist P表示p为空时 为真 in表示一个标量和一元关系的关系。例如:s in P表示当s与P中的某个值相等时 为真; s not in P 表示s与P中的每一个值都不相等时 为真

    文章转载  原出处 :http://blog.sina.com.cn/s/blog_67eb150a0100kesw.html

  • 相关阅读:
    c++ 虚继承与继承的差异 (转)
    主题:PageRank解释
    (转)开源爬虫larbin分析
    Django随笔
    原生爬虫小Demo
    SVN
    Python的正则表达式与JSON
    类库 方法 模块等
    笔记
    自动补全Typeahead
  • 原文地址:https://www.cnblogs.com/alexlo/p/2694081.html
Copyright © 2011-2022 走看看