zoukankan      html  css  js  c++  java
  • sql中的in(三值逻辑)与exists(二值逻辑)(by atkfc)

        上网查了一下,关于sql中的in和exists,大家普遍关心的是效率问题:通常情况下采用exists要比in效率高,因为IN不走索引,但要看实际情况具体使用:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

        今天我要说的是sql中的in(三值逻辑)与exists(二值逻辑)。所谓二值逻辑,即true或false,三值逻辑,即true或false或unknown。(环境为sqlserver 2008)

        首先,请大家看一个现象:(ad:http://www.cnblogs.com/atkfc)

    --现象:
    declare @a1 int=22
    if @a1 in (1,22,null) print 'y1' else print 'n1'  --result:y1
    if @a1 in (1,2,null) print 'y1' else print 'n1'  --result:n1
    if @a1 not in (1,2,null) print 'y2' else print 'n2'  --result:n2
    --分析:@a1 not in (1,2,null)<=>not @a1 in (1,2,null)<=>not(@a=1 or @a=2 or @a=null)<=>not(false or false or unknown)<=>not unknown<=>unknown

        然后,举一个示例,以飨读者:

    STEP1:建两个表

    --table tbl1:
    if OBJECT_ID('tbl1','U') is not null drop table tbl1
    create table tbl1
    (id int not null primary key,
    age int
    )
    insert tbl1 values(1,1),(2,2),(3,3),(4,4),(5,null)
    select * from tbl1
    --table tbl2:
    if OBJECT_ID('tbl2','U') is not null drop table tbl2
    create table tbl2
    (id int not null primary key,
    age int
    )
    insert tbl2 values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,null)
    select * from tbl2

    --两张表tbl1、tbl2查询结果如下图:

        

    STEP2:执行下面几句

    --e.g.1
    select * from tbl2 t2 where age in(select t1.age from tbl1 t1)
    --e.g.2
    select * from tbl2 t2 where age not in(select t1.age from tbl1 t1)
    --e.g.3
    select * from tbl2 t2 where age not in(select t1.age from tbl1 t1 where t1.age is not null)
    --e.g.4
    select * from tbl2 t2 where exists(select t1.age from tbl1 t1 where t1.age =t2.age)
    --e.g.5
    select * from tbl2 t2 where not exists(select t1.age from tbl1 t1 where t1.age =t2.age)
    --e.g.6
    select * from tbl2 t2 where not exists(select t1.age from tbl1 t1 where t1.age =t2.age) and t2.age is not null

         --执行结果如下图:(ad:http://www.cnblogs.com/atkfc)

         

    STEP3:分析(P is Problem, S is Solution):

    P1:当对至少返回一个null值的子查询使用not in时,外部查询总会返回一个空集。对于来自外部表的某个值,如果已经知道这个值会在子查询返回的集合中出现,那么外部查询将不会返回这个值,因为外部查询原本就是要返回不会在子查询返回集合中出现的值;如果外部表中的这个值没有在子查询返回的已知值集合中出现,那么外部查询仍然不会返回这个值,因为这时无法确切的判断这个值是否包含null的集合所涵盖的范围。
    S1toP1:显式地排除null值,如e.g.3,加条件where t1.age is not null
    S2toP1:隐式地排除null值,如e.g.5,使用not exists取代not in

    小结: 1.当一个列不应该允许为null时,把它定义为not null很重要。加强数据的完整性定义,比很多人想象的要重要的多。
        2.与in不同的是,exists使用的是二值逻辑,所以exists总是返回true或false,而绝不会返回unknown,当子查询遇到null值时,表达式的计算结果就为unknown,该行会被过滤掉。就exists来说,它可以自然的消除null值的情况,好像他们根本不存在。这样exists只处理已知的值。因此,使用not exists比使用not in更安全。(ad:http://www.cnblogs.com/atkfc)

     

  • 相关阅读:
    cordova 里js和oc通信原理
    awakeFromNib
    CALayer树形结构
    SDWebImage原理,转载
    gcd多线程
    block的存储形态
    关于weak对象什么时候释放
    Swift是否和OC一样有runtime机制
    大数据基础
    python进行离线打包并安装
  • 原文地址:https://www.cnblogs.com/atkfc/p/2791178.html
Copyright © 2011-2022 走看看