日期:2014-05-18  浏览次数:20550 次

SQL server 中not in 和 no exists的区别
最近在看数据库.看到not in 和 no exists 时,我被弄糊涂了.下面是我的测试.
TestFirstTable
1 Testone 123456
2 TestTwo 1111111
3 testthr 12231231
4 testfour 22324
5 testfour 22324
6 testfour 22324

TestTwoTable
1 testone 123231
2 testone 123231
4 testone 123231
6 testone 123231
8 testone 123231

我写了以下五个查询语句: 
1)
select * from TestFristTable as a where a.TestID not in(select TestID from TestTwo)

2)
select * from TestFristTable where not exists(select TestTwo.TestID from TestTwo,TestFristTable where TestTwo.TestID=TestFristTable.TestID)

3)
select TestTwo.TestID from TestTwo,TestFristTable where TestTwo.TestID=TestFristTable.TestID

4)
select * from TestFristTable where not exists(select TestID from TestTwo where TestTwo.TestID=TestFristtable.TestID)

5)
select TestID from TestTwo where TestTwo.TestID=TestFristtable.TestID

第5个在执行时会报错,可以选中前四个一起执行得到的结果是:

1)
3 testthr 12231231
5 testfour 22324

2) 


3)
1
2
4
6

4)
3 testthr 12231231
5 testfour 22324

这就出现问题了.
第二个语句的查询结果是空,但是子查询语句的结果却有值 .
3)
1
2
4
6
更奇怪的是第4、5两句。第5句是第4句的子查询。当执行第五句时回报错,但是第4句却可以查找出我想要的结果 
4)
3 testthr 12231231
5 testfour 22324
为什么呢?
为什么2、3,子查询语句有值,但整个语句没值 。4、5 子查询语句单独执行都会报错,为什么整个查询语句却可以查出结果?

------解决方案--------------------
几乎一样.不过no exists 比not in 教快.
另:如果存在多个字段的比较,则只能用not exists

例如查询a表ID不在B表的id
select a.* from a where id not in (select id from b)
select a.* from a where not exists(select 1 from b where b.id = a.id)

例如查询a表ID不在B表的id1+id2
select a.* from a where not exists(select 1 from b where b.id1 = a.id1 and b.id2 = a.id2)



------解决方案--------------------
我写了以下五个查询语句: 
1)
select * from TestFristTable as a where a.TestID not in(select TestID from TestTwo)
====
正确

2)
select * from TestFristTable where not exists(select TestTwo.TestID from TestTwo,TestFristTable where TestTwo.TestID=TestFristTable.TestID)
====
语法正确,逻辑错误。
红色部分是单独的语句,执行总是有结果,所以not exists总是False,所以结果是空。

3)
select TestTwo.TestID from TestTwo,TestFristTable where TestTwo.TestID=TestFristTable.TestID
====
正确。
这是老式的JOIN语法,建议用INNER JOIN代替。

4)
select * from TestFristTable where not exists(select TestID from TestTwo where TestTwo.TestID=TestFristtable.TestID)
====
正确。逻辑上与1)等价,当TestTwo.TestID不包含NULL值时。

5)
select TestID from TestTwo where TestTwo.TestID=TestFristtable.TestID
====
语法错误。
4)是相关子查询,子查询部分不能作为单独语句执行。

------解决方案--------------------
SQL code

其实LZ搞清楚in和exists的区别就大概明白了
IN 
确定给定的值是否与子查询或列表中的值相匹配。 

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

比较使用 EXISTS 和 IN 的查询 

exists()后面的子查询被称做相关子查询   他是不返回列表的值的.只是返回一个ture或false的结果,其运行方式是先运行主查询一次   再去子查询里查询与其对应的结果   如果是ture则输出,反之则不输出.再根据主查询中的每一行去子查询里去查询.   
    
  in()后面的子查询   是返回结果集的,换句话说执行次序和exists()不一样.子查询先产生结果集,然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出.

------解决方案--------------------
逻辑要求:查询T1表中不在T2表的记录。

方法1:SELECT * FROM T1 WHERE T1.ID NOT IN (SELECT T2.ID FROM T2)
方法1.1:SELECT * FROM T1 WHERE T1.ID NOT IN (SELECT T2.ID FROM T2 WHERE T2.ID IS NOT NULL)
====
以上两个都是不相关子查询(独立子查询),子查询部分可以作为单独语句执行。
方法1和方法1.1的区别在于一点细微的逻辑差异(与NULL和三值逻辑有关),当T2.ID列包含NULL时,查询结果会有区别。
参看:http://topic.csdn.net/u/20100826/18/7b81012a-b5c4-48b1-b5d1-40a92f3e0388.html

方法2:SELECT * FROM T1 WHERE NOT EXISTS (SELECT * FROM T2 WHERE T2.ID = T1.ID)
方法2的常见错误写法:SELECT * FROM T1 WHERE NOT EXISTS (SELECT * FROM T2,T1 WHER