2017-01-09 115 views
19

我正在運行以下查詢以從員工表中獲得第三高薪水,並且它正常工作,但我無法理解其邏輯。子查詢值如何與主查詢(左邊部分)匹配。有人能解釋一下這個查詢背後的邏輯是什麼嗎?查詢的邏輯是什麼?

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
      from employee as e2 
      where e1.salary<=e2.salary) 

PS:我能理解行count()收益數(所有記錄都是唯一的)。

+6

對於一個非常基本的理解水平的人;爲什麼這麼複雜?難道你不能用RANK或ROW_NUMBER與ORDER BY一起完成這項工作嗎?是否有像OPs例子那樣的繼承價值? –

+2

@StianYttervik我猜猜誰寫了它不知道RANK或ROW_NUMBER是否存在 – Caleth

+2

好吧,關閉選民。你這一切都是錯的嗎?這是一個推薦問題。 (嚴重的是,你甚至可以從那裏得到什麼?)這個問題已經足夠清晰了,正如幾個很好的答案所證明的,這些答案解釋了查詢的功能。我甚至認爲這個問題不是「基本」的;當您仍然掌握SQL基礎知識時,被查詢困惑並不是不合理的。 (嘿,即使你知道你用SQL的方式,它可能需要花一分鐘的時間來揣摩它。)如果你要投票結束,*先找出一個好的理由*。 – jpmc26

回答

5

employee表的所有工資e1將轉交給sub-querySub-query會發現所有salaries這些都小於通過的salary並算上它。

對於通過工資如果子查詢返回算作3那麼工資將導致

考慮有5條記錄員工表時1e1通過

1 
2 
3 
4 
5 
6 
7 
8 

,子查詢將如

現在子查詢中的計數將是8,因爲所有的記錄都大於或等於1計數不等於3所以salary 1將不予退還

2從E1通過

,子查詢會像

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
      from employee as e2 
      where 2<=e2.salary) 

現在子查詢中的計數將是7因爲除了1箇中的所有記錄都大於或等於2計數不等於3,從而Salary 2它不會返回


6從E1通過,子查詢會像

select e1.salary 
from employee as e1 
where 3 = (select count(salary) 
      from employee as e2 
      where 6<=e2.salary) 

現在有三個記錄大於或等於6(即)6,7,8所以計數爲3條件滿足。所以salary 6將被退回

+0

或者你的意思是6 <= 6 –

+0

@JasonClark - 對不起我沒有得到那.. –

+0

我想清除子查詢過程之後,Where子句,假設如果我有4記錄像25000,15000,10000,17000.然後如何subquery將執行這些值,如果我想獲得第三最高薪水? –

1

其實這很簡單。第二個查詢選擇當前(選定)員工(e1)薪水較低的所有員工。然後我們說薪水較低或同等水平的員工人數應該是3.這導致獲得第三高的薪水。

21

該查詢基本上是說:

for each row in employee assign to e1 
    count = 0 
    for each row in employee assign to e2 
     if e1.salary <= e2.salary 
      count = count + 1 
     end if 
    end for 
    if count = 3 
     add e1 to result set 
    end if 
end for 
return result set 

總之在它正在訪問表中的第二次僱員表中的每一行,並用低於或等於工資計算的行數。如果正好有3個,它會將該行添加到結果中。

值得指出的是,如果有多名員工薪水相同,這可能會出錯。您可能想要的是帶有排名功能的查詢。類似這樣的:

SELECT salary 
FROM 
    (SELECT 
     salary 
     ,DENSE_RANK() OVER (ORDER BY salary DESC) [rank] 
    FROM employee) t 
WHERE 
    [rank] = 3 

究竟是什麼意思是「第三最高」也許有點含糊不清。如果我們有薪金8,8,6,5上面會返回5.如果我們想6,你將需要改變DENSE_RANK到ROW_NUMBER這樣的:

SELECT salary 
FROM 
    (SELECT 
     salary 
     ,ROW_NUMBER() OVER (ORDER BY salary DESC) [rank] 
    FROM employee) t 
WHERE 
    [rank] = 3 

的DENSE_RANK以上版本也返回多行受到影響如果有第三名的平局。這是否合乎要求取決於所要求的內容,但可以通過對薪水使用匯總函數來減少這一點。

SELECT MAX(salary) 
FROM 
    (SELECT 
     salary 
     ,DENSE_RANK() OVER (ORDER BY salary desc) [rank] 
    FROM employee) t 
WHERE 
    [rank] = 3 
6

考慮這些值:

Salary: 
1 
2 
3 
4 
5 
6 
7 
8 

e1 e2 
1 1 
2 2 
3 3 
4 4 
5 5 
6 6 
7 7 
8 8 

對於e1.1有8行中e2是大於或等於e1.1

對於e1.2e2中有7行大於或等於e1.2

...

對於e1.6有3行中e2是大於或等於e1.6

這是一個相當奇怪和令人困惑的選擇語句。我只想重寫使用DENSE_RANK窗口功能,因爲如果你有同樣的薪水幾行,你就不會得到正確的結果:在5

DECLARE @t TABLE (i INT) 
INSERT INTO @t 
VALUES (1), 
     (2), 
     (3), 
     (4), 
     (5), 
     (6), 
     (8), 
     (8); 


WITH cte 
      AS (SELECT * , 
         DENSE_RANK() OVER (ORDER BY i DESC) AS rn 
       FROM  @t 
      ) 
    SELECT * 
    FROM cte 
    WHERE rn = 3 

的結果,而你最初的SELECT語句將導致6,我相信並不是第三高的薪水。

+2

對於大多數人來說,「第三高的工資」是指第三高薪工資的工資,所以5,6,8,8的預期結果是6. –