为什么MySQL允许您按未选择的列进行分组

时间:2014-03-04 16:40:12

标签: mysql sql group-by

我正在读一本关于SQL的书(Sams在10分钟内自学SQL),尽管它的标题很好。但是关于群组的章节让我感到困惑

“分组数据是一个简单的过程。所选列(列表列表如下) 查询中的SELECT关键字)是可以在GROUP中引用的列 BY子句。如果在SELECT语句中找不到列,则无法在其中使用 GROUP BY子句。如果你考虑一下,这是合乎逻辑的 - 如何在数据上对数据进行分组 报告是否未显示数据? “

为什么我在MySQL中运行这个语句有效呢?

select EMP_ID, SALARY
from EMPLOYEE_PAY_TBL
group by BONUS;

2 个答案:

答案 0 :(得分:5)

你是对的,MySQL确实允许你创建含糊不清且具有任意结果的查询。 MySQL相信你知道你在做什么,所以你有责任避免这样的查询。

您可以让MySQL以更标准的方式强制执行GROUP BY:

mysql> SET SQL_MODE=ONLY_FULL_GROUP_BY;

mysql> select EMP_ID, SALARY
  from EMPLOYEE_PAY_TBL
  group by BONUS;

ERROR 1055 (42000): 'test.EMPLOYEE_PAY_TBL.EMP_ID' isn't in GROUP BY

答案 1 :(得分:4)

因为这本书错了。

根据ANSI标准,group by中的列与select中的列只有一个关系。如果列在select中,没有聚合函数,那么它(或它所在的表达式)需要在group by语句中。 MySQL实际上放松了这种情况。

这甚至是有用的。例如,如果要从表中为每个组选择id最高的行,则编写查询的一种方法是:

select t.*
from table t
where t.id in (select max(id)
               from table t
               group by thegroup
              );

(注意:还有其他方法可以编写这样的查询,这只是一个例子。)

编辑:

您建议的查询:

select EMP_ID, SALARY
from EMPLOYEE_PAY_TBL
group by BONUS;

可以在MySQL中运行,但可能不在任何其他数据库中(除非BONUS碰巧是表上名称不好的主键,但这是另一回事)。它将为BONUS的每个值生成一行。对于每一行,它将从该组中的行中获得任意EMP_IDSALARY。文档实际上说“不确定”,但我认为任意更容易理解。

你应该真正知道这种类型的查询只是不使用它。 SELECT中的所有“裸”列(即没有聚合函数)都应该在GROUP BY中。大多数数据库都需要这样做。请注意,这是本书所说的。这样做没有问题:

select EMP_ID
from EMPLOYEE_PAY_TBL
group by EMP_ID, BONUS;

除了您可能会为同一EMP_ID获取多行而无法区分它们。