SQL中的GROUP BY子句是多余的吗?

时间:2010-12-22 01:12:00

标签: sql group-by

每当我们在SQL中使用聚合函数(MINMAXAVG等)时,我们必须始终GROUP BY所有非聚合列,例如:< / p>

SELECT storeid, storename, SUM(revenue), COUNT(*)
FROM Sales 
GROUP BY storeid, storename

当我们在SELECT语句中使用函数或其他计算时,它变得更具侵入性,因为它也必须复制到GROUP BY子句。

SELECT (2 * (x + y)) / z + 1, MyFunction(x, y), SUM(z)
FROM AnotherTable
GROUP BY (2 * (x + y)) / z + 1, MyFunction(x, y)

如果我们要更改SELECT语句,我们必须记住对GROUP BY子句进行相同的更改。

GROUP BY子句是多余的吗?

  • 如果确实如此,那么为什么SQL中会出现GROUP BY子句?
  • 如果不是这样,那么GROUP BY给我们的额外功能是什么?

4 个答案:

答案 0 :(得分:8)

  

每当我们在SQL中使用聚合函数(MIN,MAX,AVG等)时,我们必须始终GROUP BY所有非聚合列

一般情况下并非如此。例如,MySQL不需要这样,而且SQL标准也没有这样说。

  

当我们在SELECT语句中使用函数或其他计算时,它变得更具侵入性,因为它也必须复制到GROUP BY子句。

一般情况下也不是这样。 MySQL(也可能是其他数据库)允许在GROUP BY子句中使用列别名:

SELECT (2 * (x + y)) / z + 1 AS a, MyFunction(x, y) AS b, SUM(z)
FROM AnotherTable
GROUP BY a, b
  

如果不是这样,那么GROUP BY给我们的额外功能是什么?

指定分组内容的唯一方法是使用GROUP BY子句。您不一定要从SELECT中提到的列中推断出它。实际上,您甚至不必选择GROUP BY中提到的所有列:

SELECT MAX(col2)
FROM foo
GROUP BY col1
HAVING COUNT(*) = 2

答案 1 :(得分:5)

我可能同意你所说的话,但在所有案例中并不多余。

考虑一下:

SELECT FirstName 
       + ' (' + REPLACE(Address1, ',', ' ') + ' '
       + REPLACE(Address2, ',', ' ') + ', '
       + UPPER(State) + ' '
       + 'USA)',
       COUNT(*)
FROM Profiles
GROUP BY FirstName, Address1, Address2, State

在这种情况下,我只想要相同名字,相同地址的个人资料 如您所见,我不必在SELECT语句中重复GROUP BY的“复杂”操作。

我认为允许这种“有时像这样,有时候就是这样”,你在大部分时间都不得不做重复工作。

答案 2 :(得分:1)

GROUP BY子句不是多余的 - 它的功能是定义聚合函数的工作范围。您认为优化器应该从SELECT子句读取以了解分组的范围,但最早可以在ORDER BY子句中访问列别名(MySQL除外,其中{ {1}}和GROUP BY子句支持列别名)。目前,没有办法支持你的期望。 ANSI标准很好,但实际情况是ANSI标准并非由供应商完全实现。这是狩猎&amp; peck支持,就像PostgreSQL 8.4+支持比Oracle更多的分析功能(当然比SQL Server更多)。

MySQL和SQLite支持省略HAVING中的列,但根据文档,这些列值是任意的 - 不能保证一致地返回值。并且分组的范围也不同,这有可能对返回的结果集产生巨大影响。然后是在需要移植到其他数据库时依赖供应商特定语法的问题,因为DB2,Oracle,SQL Server和PostgreSQL不支持该功能。

但随着分析/窗口/排名功能的出现,您可以在没有GROUP BY的情况下获得聚合功能。 IE:

GROUP BY

它更冗长,并且容易出错,因为您无法定义适用于查询中所有分析函数的SELECT t.id, COUNT(t.column) OVER(PARTITION BY t.id) AS num, SUM(t.column) OVER(PARTITION BY t.id) AS sum FROM YOUR_TABLE t / PARTITION BY。目前......但Google Analytics不会很快取代聚合 - 支持从Oracle 9i,SQL Server 2005+和PostgreSQL 8.4+开始。我知道DB2支持分析,但除此之外我不知道细节。

答案 3 :(得分:0)

  1. (2 * (x + y)) / z + 1, MyFunction(x, y)之后的主要内容是GROUP BY,需要知道如何汇总。
  2. (2 * (x + y)) / z + 1, MyFunction(x, y)之后的SELECT是可选的。您希望结果如何变为,而不会影响sum()
    就像BeemerGuy所说,2.并不总是与1相同。