2017-03-28 57 views
1

希望得到一些幫助。 SQL新手,並試圖保持頭腦清醒。學習SQL:需要幫助使用HAVING從聚合獲得最小結果

我一直在考慮這個任務:

「使用HAVING,確定其直接下屬有最低工資平均。」

我的邏輯是在衍生表上加入一個連接,以計算每個具有直接報告的經理的工作人員的AVG工資。這個結果然後通過HAVING子句被過濾到MIN值。

SELECT Flash.firstname, Flash.lastname, Wally.AVGSalary, 
     Wally.[Direct Reports] FROM CrewMembers Flash 
    JOIN 
    (
     SELECT Barry.crewMemberId, AVG(Zoom.salary) AS 'AVGSalary', COUNT(Zoom.firstname) AS 'Direct Reports' 
        FROM CrewMembers Barry 
      JOIN CrewMembers Zoom 
          ON Zoom.managerId = Barry.crewMemberId 
     GROUP BY Barry.crewMemberId 
    ) 
    AS Wally ON Wally.crewMemberId = Flash.crewMemberId 

GROUP BY Flash.firstname, Flash.lastname, Wally.AVGSalary, Wally.[Direct Reports] 

HAVING MIN(Wally.AVGSalary) in (Wally.AVGSalary) 

ORDER BY Wally.AVGSalary asc 

我得到這個結果:

firstname lastname AVGSalary Direct Reports 
Mike  Patton  33666.500000 2 
Kurt  Corgan  37300.000000 2 
Amber  Bruckner 45851.666666 3 
Doug  Adams  86250.000000 2 
Montgomery Scott  92500.000000 2 
James  Kirk  132666.750000 3 

我難倒。我需要它給我帶最低價值的那一排,它給我所有的價值。我盯着這個,無法弄清楚我做錯了什麼。

我知道,通過在線觀察線索,使用TOP是一種過濾項目的方式,但尚未引入,我希望保留在迄今爲止已建立的參數範圍內。

任何批評我寫的或任何幫助將會很棒。就像我說的,我是新的,只是想跟上。

感謝,

Ĵ

回答

0

你需要另一個子查詢(如果你不想使用上/窗口功能/等):

select Flash.firstname, 
    Flash.lastname, 
    Wally.AVGSalary, 
    Wally.[Direct Reports] 
from CrewMembers Flash 
join (
    select Barry.crewMemberId, 
     AVG(Zoom.salary) as 'AVGSalary', 
     COUNT(Zoom.firstname) as 'Direct Reports' 
    from CrewMembers Barry 
    join CrewMembers Zoom on Zoom.managerId = Barry.crewMemberId 
    group by Barry.crewMemberId 
    having avg(Zoom.salary) = (
      select min(salary) 
      from (
       select AVG(Zoom.salary) as salary 
       from CrewMembers Barry 
       join CrewMembers Zoom on Zoom.managerId = Barry.crewMemberId 
       group by Barry.crewMemberId 
       ) t 
      ) 
    ) as Wally on Wally.crewMemberId = Flash.crewMemberId 

您可以使用top

select top 1 Flash.firstname, 
    Flash.lastname, 
    Wally.AVGSalary, 
    Wally.[Direct Reports] 
from CrewMembers Flash 
join (
    select Barry.crewMemberId, 
     AVG(Zoom.salary) as 'AVGSalary', 
     COUNT(Zoom.firstname) as 'Direct Reports' 
    from CrewMembers Barry 
    join CrewMembers Zoom on Zoom.managerId = Barry.crewMemberId 
    group by Barry.crewMemberId 
    ) as Wally on Wally.crewMemberId = Flash.crewMemberId 
order by Wally.AVGSalary 

另一種方法是使用窗口功能rank

select Flash.firstname, 
    Flash.lastname, 
    Wally.AVGSalary, 
    Wally.[Direct Reports] 
from CrewMembers Flash 
join (
    select Barry.crewMemberId, 
     AVG(Zoom.salary) as 'AVGSalary', 
     COUNT(Zoom.firstname) as 'Direct Reports', 
     rank() over (order by AVG(Zoom.salary)) as rnk 
    from CrewMembers Barry 
    join CrewMembers Zoom on Zoom.managerId = Barry.crewMemberId 
    group by Barry.crewMemberId 
    ) as Wally on Wally.crewMemberId = Flash.crewMemberId 
where Wally.rnk = 1; 
+0

嘿GurV,我在網上看過TOP,但那還沒有在課程中介紹過。 – ROKPLYR

+0

是的,我想過使用WHERE。顯然,我必須使用HAVING來獲得結果。它似乎使這個問題有目的的荒謬。 – ROKPLYR

+0

@ROKPLYR - 剛剛通過子查詢更新了答案(見第一個) – GurV

0

你應該使用HAVING與平等的,而不是IN所以像:

HAVING Wally.AVGSalary = MIN(Wally.AVGSalary)

你的情況與IN將返回所有行,你想只希望與工資等於最低的一個。

+0

HAVING Wally.AVGSalary = MIN(Wally.AVGSalary)給了我相同的結果 – ROKPLYR

0

嘗試:

Select crewMemberId, avgSalary 
From (Select s.crewMemberId, 
     AVG(d.salary) avgSalary 
     From CrewMembers d join CrewMembers s 
     on s.crewMemberId = d.managerId 
     group by s.crewMemberId) x 
Where avgSalary = 
    (Select Min(avgSalary) 
    from (Select s.crewMemberId, 
      AVG(d.salary) avgSalary 
      From CrewMembers d join CrewMembers s 
       on s.crewMemberId = d.managerId 
      group by s.crewMemberId)x)  

- 在臨時表變量使用的示例數據:

declare @e table(crewmemberId int primary key not null, 
       managerId int null, salary decimal) 
Insert @e(crewmemberId, managerId, salary) 
values (1, null, 23), 
     (2,1,45), (3,1,33), (4,1,80), 
     (5,2,14), (6,2,8), (7,2,12), 
     (8,3,11), (9,3,5), (10,3,2), 
     (11,4,51), (12,4,38), (13,4,17) 

Select crewMemberId, avgSalary 
From (Select s.crewMemberId, 
     AVG(d.salary) avgSalary 
     From @e d join @e s 
     on s.crewMemberId = d.managerId 
     group by s.crewMemberId) x 
Where avgSalary = 
    (Select Min(avgSalary) 
    From (Select s.crewMemberId, 
      AVG(d.salary) avgSalary 
      From @e d join @e s 
      on s.crewMemberId = d.managerId 
      group by s.crewMemberId)x)   

這給出crewmemberId = 3,平均工資= 6.0000;

如果兩個或多個經理的直接聘用具有相同的平均工資,則它具有生成多個結果的優勢。