为什么“ANY”不能正常工作?

时间:2011-11-03 18:03:51

标签: sql oracle oracle10g

我正在使用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? 阅读第一个答案。最好避免使用任何/部分,全部。

2 个答案:

答案 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) )