我很难理解在此查询中使用GROUP BY
并正在寻求澄清:
Flights(flno: integer, from: string, to: string, distance: integer, departs: time, arrives: time, price: real)
Aircraft(aid: integer, aname: string, cruisingrange: integer)
Certified(eid: integer, aid: integer)
Employees(eid: integer, ename: string, salary: integer)
问题是:对于巡航范围超过1000英里的所有飞机,找到该飞机的名称和所有飞机认证的平均工资。
SELECT Temp.name, Temp.AvgSalary
FROM ( SELECT A.aid, A.aname AS name,
AVG (E.salary) AS AvgSalary
FROM Aircraft A, Certified C, Employees E
WHERE A.aid = C.aid AND
C.eid = E.eid AND A.cruisingrange > 1000
GROUP BY A.aid, A.aname ) AS Temp
为什么这里需要GROUP BY
?以下查询不会返回飞机和相应的工资,还是会返回所有不属于每架飞机的员工的平均工资?
SELECT A.aname, AVG(E.salary)
FROM Aircraft A, Certified C, Employees E
WHERE A.aid = C.aid AND
C.eid = E.eid AND A.cruisingrange > 1000
使用GROUP BY
是否更改了表的格式,以便使用GROUP BY A.aid
指定我们只对飞机表进行分组并保持认证和员工表不受影响?
答案 0 :(得分:2)
GROUP BY需要正确地进行聚合(在这种情况下,取平均值)。
如果您没有按任何方式进行分组,MySQL将在整个表格中执行此聚合。换句话说,如果您使用上次查询,它将返回巡航范围超过1000的所有飞机的平均工资,而不区分哪种飞机。试试吧,你会看到这种行为。
但是,如果您在此处使用GROUP BY
子句,您将看到每个个人飞机的平均值,其巡航范围超过1000,这就是您想要的。没有它,你就可以获得所有飞机的平均值。
对某些示例数据尝试这些查询,行为差异将变得更加清晰。
修改强>
关于你的最后几条陈述:是的,我们没有对认证或员工表做任何事情。退一步,问题是每架飞机的 。很多时候,如果给出一个问题陈述,说明你需要哪些项目的结果,那么将它作为你的group by子句是一个很好的开始。
答案 1 :(得分:1)
在SQL中编写AVG(...)时有一种本能,使用GROUP BY指定您想要的标准组的平均值。 如果没有GROUP BY子句,它只会对所有E.salary进行分组并进行平均。
答案 2 :(得分:1)
每当您选择聚合函数(如AVG,SUM,MAX,MIN等)以及其他列时,您必须按所有非聚合函数或常量的列进行分组。我能想到的唯一例外是当你使用窗口函数时(在MySQL中不可用)。
在此示例中,我不清楚为什么a.aid
未从Temp
中选择。如果有两架具有相同名称但不同ID的飞机,您可以看到类似......
aname avg
------ -------
747 100,000
747 110,000
DC10 90,000
......两个记录用于同名的不同飞机(747)
这里的小组说平均每架飞机的工资,给你每架飞机的平均工资......因为只包括你找到平均值的飞机的工资。