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