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

Mik*_*ain 12 sql group-by

每当我们使用聚合功能的SQL( ,,MIN 等),我们必须始终所有的非聚集列,例如:MAXAVGGROUP BY

SELECT storeid, storename, SUM(revenue), COUNT(*)
FROM Sales 
GROUP BY storeid, storename
Run Code Online (Sandbox Code Playgroud)

当我们在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)
Run Code Online (Sandbox Code Playgroud)

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

那么GROUP BY子句是多余的吗?

  • 如果确实如此,那么为什么SQL中会出现GROUP BY子句呢?
  • 如果不是这样,那么GROUP BY为我们提供了哪些额外功能?

Mar*_*ers 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
Run Code Online (Sandbox Code Playgroud)

如果不是这样,那么GROUP BY为我们提供了哪些额外功能?

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

SELECT MAX(col2)
FROM foo
GROUP BY col1
HAVING COUNT(*) = 2
Run Code Online (Sandbox Code Playgroud)

  • 标准很好,但是所有,但是Oracle,SQL Server和PostgreSQL要求在GROUP BY中定义所有非聚合列 - SQLite是我知道的唯一一个共享MySQL缺乏GROUP BY的数据库.MySQL文档还指出,不在GROUP BY中的非聚合列的值是任意的,该值不能保证一致. (2认同)

Bee*_*Guy 5

我可能同意你所说的话,但在所有情况下都不是多余的.

考虑一下:

SELECT FirstName 
       + ' (' + REPLACE(Address1, ',', ' ') + ' '
       + REPLACE(Address2, ',', ' ') + ', '
       + UPPER(State) + ' '
       + 'USA)',
       COUNT(*)
FROM Profiles
GROUP BY FirstName, Address1, Address2, State
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我只想要相同名字,相同地址配置文件的数量.
正如你所看到的,我没有重复的的"复杂"的行动SELECTGROUP BY发言.

我认为允许这种"有时像这样,有时候就是这样",你不得不在大多数情况下不得不重复.