2015-08-28 65 views
1

在我的員工表中,我想找到第三高薪水。有人向我提供以下查詢來執行此操作:這是什麼樣的查詢?

SELECT * 
FROM employee C1 
WHERE 3 = (SELECT Count(DISTINCT(C2.salary)) 
      FROM employee C2 
      WHERE C2.salary >= C1.salary) 

此查詢有效,但我不知道它是如何工作的。這是什麼樣的查詢?

+0

查找**相關子查詢** –

+0

這與相關子查詢選擇查詢一個更好看的執行計劃where子句 – lad2025

+0

怎麼樣'集團By'。並用'Over'命令它? – Raika

回答

3

正如其他人所說的,這種類型的查詢稱爲相關子查詢。這是一個子查詢,因爲查詢中有一個查詢,並且它是相關的,因爲內部查詢在其定義中引用了外部查詢。

考慮內部查詢:

SELECT Count(DISTINCT(C2.salary)) 
FROM employee C2 
WHERE C2.salary >= C1.salary 

在概念上,該內查詢將被一次由WHERE子句之前外部查詢產生的每行計算被施加,基本上爲一次每一行中employee。它會產生一個單一的值,從employee的行數,其中工資小於外部行的工資。

外部查詢將僅返回內部查詢生成的值恰好爲3的記錄。假設唯一的薪水值,employee表中只有一行,其中將有3個記錄的薪水值大於或等於它(一行),並且一行必然是第三高的工資值。

它很聰明,但不必要的奇怪,可能不像最直接的事情那樣優化。

+0

如果您正在尋找關於如何工作的更多細節,請將相關子查詢從WHERE塊移至SELECT中的列聲明。這將顯示爲每行輸出生成的值,並可能使事情更清晰。 – lyrisey

1

也許一個更好的解決辦法是

SELECT TOP 1 * 
FROM (
     SELECT TOP 3 * FROM employee ORDER BY Salary DESC 
    ) t 
ORDER BY Salary ASC 

比相關子查詢更易於讀取,更高效。

+0

如果最高薪水有重複,那麼使用這種方法獲得第三高薪水將很困難。http://sqlfiddle.com/#!3/3278e/1 – JamieD77

0

也可以用一個公共表格表達式來重寫。

WITH top_three 
AS 
(
    SELECT TOP 3 * FROM employee ORDER BY Salary DESC 
) 
SELECT TOP 1 * 
FROM top_three 
ORDER BY Salary ASC; 

或者,如果您需要在此查找其他等級,則可以使用row_number()。

WITH ranked 
AS 
(
    SELECT rank = ROW_NUMBER()OVER(ORDER BY Salary DESC), * 
    FROM employee 
    ORDER BY Salary DESC 
) 
SELECT * 
FROM ranked 
WHERE rank = @whatever_rank_you_want; 
+1

您需要通過您的CTE選擇添加訂單,否則它將帶回一個隨機的TOP 1行。 –

+0

確實是固定的。謝謝。 – saarrrr

1

您也可以使用Dense_Rank將薪水最高的排名降到最低,然後選擇排名第三的薪水。如果排名前2位與我上面的其他答案相同,這也可以防止您獲得錯誤的薪水。這比重複計數一個也

SELECT * 
FROM (
    SELECT *, 
      DENSE_RANK() OVER (ORDER BY Salary DESC) salary_rank 
    FROM employee e 
    ) t 
WHERE salary_rank = 3