我有下表:
学生:
+------+---------+
| Snum | Sname |
+------+---------+
| S1 | Charles |
| S2 | Amy |
| S3 | John |
+------+---------+
课程:
+-----+------------+
| cid | coursecode |
+-----+------------+
| C1 | CMPT222 |
| C2 | ASC111 |
+-----+------------+
注册:
+------+-----+
| sid | cid |
+------+-----+
| S1 | C1 |
| S2 | C2 |
+------+-----+
一般来说,我有3个学生,其中2个已经注册。
查询为:查找未注册的数字:
SELECT DISTINCT S.snum
FROM Student S
WHERE S.snum! = any (SELECT E.snum FROM Enrolled E )
此查询返回:
1
2
3
错了。
我的理解是:对于外部查询中的每个元组,ANY将检查是否存在至少一个元组。如果是,则返回TRUE。如果我们使用!=,那么它应该返回3。
我想念什么?
答案 0 :(得分:0)
这是您的查询:
SELECT DISTINCT S.snum
FROM Student S
WHERE S.snum <> any (SELECT E.snum FROM Enrolled E )
基本上,如果子查询返回多个值,则条件将始终为true。为什么?好吧,考虑返回的集合是否为1
和2
。好吧,如果将值与其中之一进行比较,则条件始终为真。请记住:1 <> 2
。因此,如果该值与第一个匹配,则第二个不匹配。
有简单的方法可以解决此问题。例如:
WHERE NOT (S.snum = any (SELECT E.snum FROM Enrolled E ))
或者:
WHERE S.snum NOT IN (SELECT E.snum FROM Enrolled E )
实际上,我不喜欢NOT IN
,因为它对待NULL
值的方式有所不同。在这种情况下,我更喜欢NOT EXISTS
。
答案 1 :(得分:0)
因为您要评估的谓词始终为真,所以= any()
至少有一个等价项。不等于或<> any()
至少等于一个。由于子查询返回的集合,最后一个谓词始终为true,而前一个谓词仅为s1
和s2
值。
请注意,如果子查询仅返回一个值,则结果选择将有所不同。
详细解释
您的子查询返回以下值:s1
和s2
。然后,您的rdbms逐行评估谓词。然后,
s1
<> s1
-> false
s1
<> s2
-> true
谓词评估,true
因为any()
。
下一个值
s2
<> s1
-> true
谓词评估true
...第三个值:
s3
<> s1
-> true
请注意,some()
和any()
是等效的子句。
将any()
视为or
门。每次找到一个“真”(输入),输出就是“真”。