学习 SQL:需要帮助使用 HAVING 从聚合中获取 MIN 结果
Learning SQL: Need help Using HAVING to get the MIN result from an aggregate
希望得到一些帮助。 SQL 的新手,努力保持头脑清醒。
我接到了这个任务:
"Using HAVING, determine whose Direct Reports have the lowest Avg Salary."
我的逻辑是对派生的 table 进行联接,该派生的 table 将计算每个有直接下属的经理的工作人员平均工资。然后,此结果将通过 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
我被难住了。我需要它给我 JUST 具有最小值的行,它给了我每个值。我盯着这个看,不知道我做错了什么。
我知道,通过在线查看线程,使用 TOP 是一种过滤项目的方法,但尚未介绍,我想保持在课程中已建立的参数范围内,所以远的。
任何对我所写内容的批评或任何帮助都会很棒。就像我说的,我是新手,只是想跟上。
谢谢,
J
你需要另一个子查询(如果你不想使用 top/window function/etc):
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
另一种方法是使用 window 函数 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;
您应该将 HAVING
与等于而不是 IN
一起使用,例如:
HAVING Wally.AVGSalary = MIN(Wally.AVGSalary)
在你 IN
的情况下,它将 return 所有行,你只想要薪水等于最低的人。
试试这个:
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)
-- 在临时 table 变量中使用示例数据:
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, Avg Salary = 6.0000;
如果直接雇用两个或更多经理的平均工资相同,它的优势是产生多个结果。
希望得到一些帮助。 SQL 的新手,努力保持头脑清醒。
我接到了这个任务:
"Using HAVING, determine whose Direct Reports have the lowest Avg Salary."
我的逻辑是对派生的 table 进行联接,该派生的 table 将计算每个有直接下属的经理的工作人员平均工资。然后,此结果将通过 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
我被难住了。我需要它给我 JUST 具有最小值的行,它给了我每个值。我盯着这个看,不知道我做错了什么。
我知道,通过在线查看线程,使用 TOP 是一种过滤项目的方法,但尚未介绍,我想保持在课程中已建立的参数范围内,所以远的。
任何对我所写内容的批评或任何帮助都会很棒。就像我说的,我是新手,只是想跟上。
谢谢,
J
你需要另一个子查询(如果你不想使用 top/window function/etc):
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
另一种方法是使用 window 函数 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;
您应该将 HAVING
与等于而不是 IN
一起使用,例如:
HAVING Wally.AVGSalary = MIN(Wally.AVGSalary)
在你 IN
的情况下,它将 return 所有行,你只想要薪水等于最低的人。
试试这个:
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)
-- 在临时 table 变量中使用示例数据:
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, Avg Salary = 6.0000;
如果直接雇用两个或更多经理的平均工资相同,它的优势是产生多个结果。