SQL中GROUP BY的基本用法

时间:2015-03-17 14:56:41

标签: mysql sql group-by

我很难理解在此查询中使用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指定我们只对飞机表进行分组并保持认证和员工表不受影响?

3 个答案:

答案 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)

这里的小组说平均每架飞机的工资,给你每架飞机的平均工资......因为只包括你找到平均值的飞机的工资。