SQL标准中真的有必要有GROUP BY吗

问题描述 投票:0回答:3

编写 SQL 几年后,我发现必须将我感兴趣的列放入

SELECT
,然后在
GROUP BY
中再次指定它们,这常常很烦人。我不禁想,我们为什么要这么做?

用户必须具体指定按哪一列进行分组的原因是什么?难道我们不能让 SQL 引擎假设 如果

SELECT
中有聚合函数,则按其余非聚合列进行分组

当您在

CASE WHEN
中有一个大的
SELECT
时,这将特别有用且更加简洁。

ansi-sql sql
3个回答
8
投票

因为它们可能并不总是完全匹配。

例如,如果我想找出每个类别的最大书籍数量,我可以这样做:

select max(cnt)
from (
    select count(*) as cnt
    from books
    group by category
    ) t;

在某些数据库(例如 Oracle)中,您甚至可以这样做:

select max(count(*))
from books
group by category;

我真的不需要指定类别列,因为我不需要它。

一些数据库(例如 Postgres)支持在 group by 子句中使用别名。


2
投票

我碰巧同意你的观点。 如果有人想要一个更深奥的

group by
——比如,省略列——那么他们可以使用子查询。

如果我不得不猜测,SQL 的编写者并不想在聚合函数中赋予如此强大的功能。 您的建议意味着

select
中的函数正在确定结果集中行的定义。 通常,
select
仅确定列。 也就是说,查询在语法上失败是一回事,因为包含的聚合没有 group by。 对于
select
中的函数来说,更改正在输出的行是另一回事。

您可以通过

select distinct

使用窗口函数。 虽然我不推荐这种语法,但你可以这样做:


select distinct x, count(*) over (partition by x) from t;

好吧,这消除了 
group by

,但您仍然必须在每个窗口函数中重复分组标准。

    


2
投票

SELECT … FROM table GROUP BY …;

首先,请记住,
SELECT

是在

FROM
GROUP BY子句之后评估的。这意味着您可以选择的内容受到这些子句结果的限制。
想象一下 
GROUP BY
生成一个新的

虚拟

表。这个虚拟表只有以下内容:


分组的列
所有列的

    摘要
  • (聚合)
  • 没有别的了
  • 每个
  • 不同
  • 组都会有一行摘要。

如果您希望在 SELECT 子句中包含特定列,则它必须是组列或摘要,因为您只能从可用内容中

SELECT

即使没有 
GROUP BY
子句,也会有一个隐含的

GROUP BY ()

产生单行摘要。一些 DBMS(不是全部)甚至允许您添加它,尽管它不会改变任何东西。

请注意,
GROUP BY
摘要中的行数受您要分组的列数的影响。一般来说,行数类似于 (DISTINCT Group1)*(DISTINCT GROUP2) 等。这意味着您肯定不想按超出实际需要的数量进行分组。

例外情况

假设你有这样的声明: SELECT state, name, count(*) FROM customers GROUP BY state;

这当然会失败。当一个状态有多个值时,选择

name
 有何意义?

但是,在传统模式下,MySQL 会让您这样做:它将选择

one
名称来配合状态。然而,无法保证是哪一个,因此它的价值值得怀疑。

假设您想按月分组。您可能希望显示月份名称,但按月份编号排序。在这里您需要将两者分组。使用伪日期函数: SELECT monthname, count(*) FROM data GROUP BY monthname, monthnumber ORDER BY monthnumber;

这只不过是一种解决方法。它利用了这样一个事实,即每个月份名称都有一个月份编号,因此没有真正的进一步分组。它只是为了获取

GROUP BY
 虚拟表中的两个值。


© www.soinside.com 2019 - 2024. All rights reserved.