2011-11-03 277 views
3

我正在學習使用Oracle 10g的SQL。我需要一個查詢來返回員工最多的部門在更新句子中使用它。我已經解決了,但我無法弄清楚,爲什麼這個查詢將無法工作:爲什麼「ANY」無法正常工作?

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

最後編輯,大概。仍然不知道發生了什麼,但行爲就好像最後一個select以某種方式返回null。所以,即使我刪除了'不',它仍然不會選擇任何東西。

如果有人有興趣,我也發現這個有用: TSQL - SOME | ANY why are they same with different names? 閱讀第一個答案。最好避免使用任何/某些,全部。

回答

1

校正(更新)

not num < any(select ...) 

應該是相同的其他查詢。你也可以嘗試這個變化:

num >= ALL(select ...) 

但我不明白你爲什麼給出錯誤的結果。也許是因爲not的優先順序。你可以trythis代替?:

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)) 
+1

我懷疑他們的意思是'num不是<任何(選擇...)'這顯然是不合法的) – onedaywhen

+0

我不知道我是否得到最後一部分,但編輯更清晰。另外,_some_和_any_應該是同一個運算符,而'num> = any(select ...)'將會返回所有的行,因爲每一行至少等於它自己。 'num> = any(select ...)'對於5,6將是真實的,因爲它們都將大於3. –

+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是否大於集合中的所有值。

然而,加入NOT操作:

WHERE NOT 1 > ALL (SELECT c FROM T T2); 

返回所有值的集合,包括空值。乍一看這似乎是錯誤的:鑑於1 > 2是假的,我們可以肯定地說,值1不大於集合中的所有值,而不管空值。

但是,在這種情況下,NOT僅僅是翻轉早先的結果,即所有沒有行的相反都是行! )

使用柱(而不是字面值爲1)進一步考慮取反比較:

WHERE NOT c > ALL (SELECT c FROM T T2); 

這一次它返回除了空值的所有行。

+0

嘿,這真的很好知道,永遠不會跨過我的腦海。但是我沒有空值。 (我編輯澄清這一點)奇怪的是,如果我手動替換最後選擇的值返回它會起作用,它甚至比我如果省略「NOT」,更改操作符'>'或'<結果將是相同的。沒有選定的行。 (SQL可能會恨我) –

+0

我想我終於得到了最後一個。如果第一個表達式爲空,則所有結果都爲空,既不是真或假,如果它是一個值,它將不能與全部結果進行比較並返回false。 這讓我覺得'num'被視爲null,但只有當我使用第二個選擇而不是值。 :S(感謝另一個奇怪的情況!) –

相關問題