我正在使用Oracle 10g学习SQL。我需要一个查询,返回拥有最多员工的部门,以便在更新语句中使用它。我已经解决了,但我无法弄清楚为什么这个查询不起作用:
select deptno
from (select deptno,
count(*) num
from emp
group by deptno)
where not num < any(select count(deptno)
from emp
group by deptno)
它让我更加困惑,因为根据文档,它应该是等效的并且优化为以下内容:
select deptno
from (select deptno,
count(*) num
from emp
group by deptno )
where not exists( select deptno,
count(*)
from emp
having count(*) > num
group by deptno)
那个工作没有错误。以下也有效:
select deptno
from (select deptno,
count(*) num
from emp
group by deptno)
where num = (select max(alias)
from (select count(deptno) alias
from emp
group by deptno))
select deptno
from emp
group by deptno
having not count(deptno) < any( select count(deptno)
from emp
group by deptno)
编辑。如果我发布内部选择的返回值,它可能会有所帮助。
第一个选择返回:
Dept. Number Employees
30 6
20 5
10 3
最后一个返回(3,5,6)
我单独检查过它们。同样奇怪的是,如果我手动设置值,它会按预期工作,并将返回30作为大多数员工的部门。
select deptno
from (select deptno,
count(*) num
from emp
group by deptno)
where not num < any(6,5,3)
我正在使用Oracle 10g 10.2.0.1.0
最后编辑,可能。仍然不知道发生了什么,但行为就好像最后一个选择以某种方式返回null。所以,即使我删除'not',它仍然没有选择任何东西。
如果有人有兴趣,我也发现这很有用: TSQL - SOME | ANY why are they same with different names? 阅读第一个答案。最好避免使用任何/部分,全部。
答案 0 :(得分:2)
这是一个类似的例子,可以澄清一些事情(标准SQL,可以很容易地转换为Oracle):
WITH T
AS
(
SELECT *
FROM (
VALUES (0),
(1),
(2),
(NULL)
) AS T (c)
)
SELECT DISTINCT c
FROM T
WHERE 1 > ALL (SELECT c FROM T T2);
这将返回空集合,这是合理的:假设表中存在空值,1 > NULL
为UNKNOWN,因此不知道值1是否大于集合中的所有值。 / p>
但是,添加NOT
运算符:
WHERE NOT 1 > ALL (SELECT c FROM T T2);
返回集合中的所有值,包括空值。乍一看这似乎是错误的:假设1 > 2
为FALSE,我们可以肯定地说,值1不大于集合中的所有值,无论空值如何。
然而,在这种情况下,NOT只是翻转前面的结果,即所有行的反面都是行! ;)
进一步考虑使用列的否定比较(而不是文字值1):
WHERE NOT c > ALL (SELECT c FROM T T2);
这次它返回除null值之外的所有行。
答案 1 :(得分:1)
更正(更新)
not num < any(select ...)
应与其他查询相同。您也可以尝试这种变化:
num >= ALL(select ...)
但我无法理解你为什么会给出错误的结果。也许是因为not
优先权。你能试试吗?:
not ( num < ANY(select ...) )
完整查询:
select deptno
from (select deptno, count(*) num from emp group by deptno)
where num >= all(select count(deptno) from emp group by deptno)
和
select deptno
from (select deptno, count(*) num from emp group by deptno)
where not ( num < any(select count(deptno) from emp group by deptno) )