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