这一直困扰着我——为什么 SQL 语句中的 GROUP BY 子句要求我包含所有非聚合列?默认情况下应该包含这些列 - 一种“GROUP BY *” - 因为我什至无法运行查询,除非它们都被包含在内。每列必须是聚合或在“GROUP BY”中指定,但似乎任何未聚合的内容都应自动分组。
也许它是 ANSI-SQL 标准的一部分,但即便如此,我也不明白为什么。有人可以帮我理解这个公约的必要性吗?
这一直困扰着我——为什么 SQL 语句中的 GROUP BY 子句要求我包含所有非聚合列?默认情况下应该包含这些列 - 一种“GROUP BY *” - 因为我什至无法运行查询,除非它们都被包含在内。每列必须是聚合或在“GROUP BY”中指定,但似乎任何未聚合的内容都应自动分组。
也许它是 ANSI-SQL 标准的一部分,但即便如此,我也不明白为什么。有人可以帮我理解这个公约的必要性吗?
很难确切地知道 SQL 语言的设计者在编写标准时的想法,但这是我的看法。
作为一般规则,SQL 要求您明确说明您的期望和意图。该语言不会尝试“猜你的意思”,而是自动填空。这是一件好事。
当您编写查询时,最重要的考虑是它会产生正确的结果。如果您犯了错误,最好让 SQL 解析器通知您,而不是猜测您的意图并返回可能不正确的结果。SQL 的声明性(您在其中声明要检索的内容,而不是如何检索它的步骤)已经很容易在不经意间犯错。将模糊性引入语言语法不会使这变得更好。
事实上,我能想到的语言允许使用快捷方式的每个案例都引起了问题。以自然连接为例——您可以在其中省略要连接的列的名称,并允许数据库根据列名推断它们。一旦列名发生变化(随着时间的推移它们自然会发生变化)- 现有查询的语义也会随之变化。这很糟糕......非常糟糕- 你真的不希望这种魔法在你的数据库代码中发生在幕后。
然而,这种设计选择的一个结果是 SQL 是一种冗长的语言,您必须在其中明确表达您的意图。这可能导致不得不编写比您喜欢的更多的代码,并抱怨为什么某些结构如此冗长......但归根结底 - 它就是这样。
我能想到保留该GROUP BY
子句的唯一合乎逻辑的原因是您可以在分组中包含未包含在您的选择列中的字段。
例如。
Select column1, SUM(column2) AS sum
FROM table1
GROUP BY column1, column3
即使 column3 未在查询的其他位置表示,您仍然可以按其值对结果进行分组。(当然,一旦你这样做了,你就无法从结果中看出为什么这些记录是按原样分组的。)
对于绝大多数最常见的场景(按每个非聚合列进行分组),这似乎是一个简单而有效的加速编码的工具。
也许"GROUP BY *"
由于在 SQL 工具中允许通过结果列号(即等)引用列已经很常见了。GROUP BY 1,2,3,
允许用户在一次击键中自动包含所有非聚合字段似乎更简单。
这很简单:您要求按 from 子句中的每一列对结果进行 sql 分组,这意味着对于 from 子句 SQL 中的每一列,sql 引擎将在内部对结果集进行分组以呈现给您。这就解释了为什么它要求您提及 from 中存在的所有列,因为它不可能将其部分分组。如果您提到 group by 子句,则只能通过对所有列进行分组来实现您的意图。这是一个数学限制。