关于EXISTS的问题
我想请大家帮我解析一下以下查询语句:
3张基本表:
S(S#,SNAME,AGE,SEX)
SC(S#,C#,GRADE)
C(C#,CNAME,TEACHER)
1、查询学习全部课程的学生姓名,语句如下:
SELETE SNAME
FROM S
WHERE NOT EXISTS
(SELECT *
FROM C
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE SC.S# = S.S#
AND SC.C# = C.C#))
NOT EXISTS的语义是什么,我应该理解为“不存在”|“不满足”?
3个SELECT语句的含义是什么,请解释一下,其中的*代表什么,表示所有属性列?特别是第2个,C和S没有关联,我不知道怎么翻译。
2、查询所学课程包含学生S3所学课程的学生学号
SELECT DISTINCT S#
FROM SC AS X
WHERE NOT EXISTS
(SELECT *
FROM SC AS Y
WHERE Y.S# = 'S3 '
AND NOT EXISTS
(SELECT *
FROM SC AS Z
WHERE Z.S# = X.S#
AND Z.C# = Y.C#))
SC AS X|Y|Z是否代表SC的三个别名,他们是代表一张SC还是三张SC,是不是产生了连接操作,什么时候需要使用AS。
3个SELECT语句的含义是什么,请解释一下。
3、查询不学C2课程的学生姓名与年龄
SELECT SNAME,AGE
FROM S
WHERE S# NOT IN
(SELECT S#
FROM SC
WHERE C#= 'C2 '))
SELECT SNAME,AGE
FROM S
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE SC.S# = S.S#
AND C#= 'C2 '))
以上有两种方法,我想问问为什么使用NOT EXISTS时前面没有属性名,是表示所有属性吗?还有为什么使用NOT EXISTS时子SELECT语句的条件多了一个SC.S#=S.S#
请大家多多指教,谢谢
[解决办法]
EXISTS同NOT EXISTS
更好的理解是
交集与差集
解析第一句SQL
SELETE SNAME
FROM S
WHERE NOT EXISTS
(SELECT *
FROM C
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE SC.S# = S.S#
AND SC.C# = C.C#))
拆开看第二部分
SELECT *
FROM C
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE SC.S# = S.S#
AND SC.C# = C.C#)
它外层的
SELETE SNAME
FROM S
WHERE NOT EXISTS
你可以看做一个查询S表的循环.挨个把S#赋值给里层S.S#
当给予1个S.S#时.里层开始判断
SELECT *
FROM SC
WHERE SC.S# = S.S#
AND SC.C# = C.C#
查询SC表中 所有 SC.S# = S.S# 并且 SC.C# = C.C# 的数据
(PS::C.C#同S.S#一样可以理解为由SELECT * FROM C 循环给值)
然后将查询SC表得到的记录集同SELECT * FROM C 取差值
就是要得到 C表中S.S# 此学生没有学习的科目.
然后再用此结果集 同 S 表取差值 排除这样的学生
[解决办法]
select * 没有确实意义 ... 只是为了满足sql 语法而已
写成 select 1 ,select 2 等都是可以的...
[解决办法]
SELECT *
FROM C
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE SC.S# = S.S#
AND SC.C# = C.C#))
这里查出来的是 一个学生没有选择的课, 如果有记录集(用a表示)则表示学生有课没有选,如果没有记录集(记录集为空用b表示)则表示该学生选择了全部的课程,然后返回学生的名字(因为b记录集为空)
[解决办法]
not Exists 最简单的理解方法
select 表1.id from 表1
where not exists
( ... 表1.id ...)
真正关注的是 表1.id 把这个放到里面的sql语句中去.
满足条件能查出东西 则 排除此表1.id
反之则保留此表1.id
和里面 select * from 表2 where 表2.id=表1.id
没有很必要的联系
[解决办法]
1.
not exist是大对小的关系,也就是说你查出来的多于exist后面的!
如果是小对大的关系,你就要用 in 了!
select * from s 相当于 select S#,SNAME,AGE,SEX from s
会省很多麻烦 但是最好把那些列名都列上,要不以后你都不知道查的是什么!尽量少用* 吧!
2.
as 是加了一个别名!,你可以把他理解成3个表但是内容完全相同!如果你一次查询多次用一个表就可以用别名!这样会看的很清晰!
[解决办法]
关了Exists 和 In
---------------------------------------------------
表A 和 表B
如果表A是个大表
表B是个小表
1、select * from 表A where id in (select id from 表B)
方法好过2
2、select * from 表A where exists(select 1 from 表B where 表A.id=表B.id)
------------------------------------------
------------------------------------------
讨论IN和EXISTS。
select * from t1 where x in ( select y from t2 )
事实上可以理解为:
select *
from t1, ( select distinct y from t2 ) t2
where t1.x = t2.y;
——如果你有一定的SQL优化经验,从这句很自然的可以想到t2绝对不能是个大表,因为需要对t2进行全表的“唯一排序”,如果t2很大这个排序的性能是不可忍受的。但是t1可以很大,为什么呢?最通俗的理解就是因为t1.x=t2.y可以走索引。但这并不是一个很好的解释。试想,如果t1.x和t2.y都有索引,我们知道索引是种有序的结构,因此t1和t2之间最佳的方案是走merge join。另外,如果t2.y上有索引,对t2的排序性能也有很大提高。
select * from t1 where exists ( select null from t2 where y = x )
可以理解为:
for x in ( select * from t1 )
loop
if ( exists ( select null from t2 where y = x.x )
then
OUTPUT THE RECORD!
end if
end loop
——这个更容易理解,t1永远是个表扫描!因此t1绝对不能是个大表,而t2可以很大,因为y=x.x可以走t2.y的索引。
综合以上对IN/EXISTS的讨论,我们可以得出一个基本通用的结论:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。
LZ:要是你有数据可以测试一下...