exists的理解
一开始对于exists的理解非常的模糊,网上的博客有几篇还有问题。还被转来转去,最后是找到了菜鸟教程SQL的exists。菜鸟教程确实是言简意赅,一下子帮助我理清了逻辑。
exists
菜鸟教程也说的很清楚了,exists并不关心元组里有啥,exists关心的是能不能有返回值而已。也就是true或者false。
EXISTS 运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False。
一条或多条这里需要画重点。非常非常重要!!!
但是这样的理解肯定是很模糊的,下面窝就来讲一讲。当然这只是窝的理解,如果有纰漏的话请留言指正。
首先exists应该是一个需要用到多表查询才需要用的一个关键字。这里的多表可以是多个相同的表或者多个不同的表。如果只需要用到一个表的情况下不太需要去使用exists。我们用一个例子来说明。
table a
ID NAME
------ ------
1 A1
2 A2
3 A3
我们来查找id>2的学生.
select * from a where exists (select * from a where id > 2);
那么结果是什么呢?
ID NAME
------ ------
1 A1
2 A2
3 A3
//当然是全部输出出来了。这是为啥呢?
首先,同样的SQL会用每个元组去对应where,然后exists只关心存不存在,按照上面,我们存在一个id>3的元组在,所以会返回一个true。
-
首先拿第一个元组去where找exists是否存在id>2,存在返回一个true,这个元组被筛选出来。
-
接下来拿第二个元组去where找exists是否存在id>2,同样存在,又返回一个true,该元组被筛选出来了。
-
同理,第三个元组也被筛选出来了。
这样就会看到最后的结果把table a原样输出了。
如果我们不用exists谓语直接这样写就能达到目的了,短小精悍又正确
select * from a where id > 2;
那么如何正确地用exists的SQL写法是什么呢?
上面也说到了,exists应该是多表查询时展现它的作用。
EXAMPLE1:
select * from a another where exists (select * from a where another.id=a.id and a.id>2);
ID NAME
------ ------
3 A3
输出确实是我们想要的,这就是为什么窝会说exists在多表查询时才能展现出自己的能力。或者说exists是可以省略的
EXAMPLE2:
select another1.id,another1.name from a another1,a another2 where another1.id=another2.id and another1.id>2;
ID NAME
------ ------
3 A3
仔细比对写法的不同就能很好的理解了,但是有一点需要注意区别,如果我们是这样写的.
EXAMPLE3:
select * from a another1,a another2 where another1.id=another2.id and another1.id>2;
ID NAME ID NAME
------ ---- ---- --------
3 A3 3 A3
通过EXAMPLE1和EXAMPLE3的比较我们可以知道重名处理的不同,EXAMPLE3很明显会先做一个笛卡尔积再进行条件判断筛查,而EXAMPLE1却没有(这里不对的话请指正)。
解释
- 我们先拿表a的第一个元组判断,在圆括号里做了一个重名处理的笛卡尔积形成了一个类似于EXAMPLE3的表b,在这个表b里进行where判断,如果存在,返回一个true,很明显这时的a.id=1是小于2的所以返回一个false,表a的该元组不被筛选出来。
- 同理,这时的a.id=2还是不小于2,返回一个false,表a的该元组也不被筛选出来。
- 这一回a.id=3大于2,所以返回一个true,表a的该元组被筛选出来。