为什么SQL强制我在GROUPBY子句中重复SELECT子句中的所有非聚合字段?

为什么SQL强制我在GROUPBY子句中重复SELECT子句中的所有非聚合字段?,sql,group-by,Sql,Group By,这件事困扰了我很长时间 99%的情况下,GROUP BY子句是SELECT子句的精确副本,减去聚合函数(MAX、SUM等)。 这打破了“不要重复自己”的原则 GROUPBY子句何时可以不包含SELECT子句减去聚合函数的精确副本 编辑 我意识到有些实现允许您在GROUP BY中使用与SELECT中不同的字段(因此99%,而不是100%),但这肯定是一个非常小的例外? 如果您使用不同的字段,有人能解释应该返回什么吗 谢谢。事实上,这不是100%的时间吗?是否存在这样的情况:您可以在select中有

这件事困扰了我很长时间

99%的情况下,GROUP BY子句是SELECT子句的精确副本,减去聚合函数(MAX、SUM等)。
这打破了“不要重复自己”的原则

GROUPBY子句何时可以不包含SELECT子句减去聚合函数的精确副本

编辑 我意识到有些实现允许您在GROUP BY中使用与SELECT中不同的字段(因此99%,而不是100%),但这肯定是一个非常小的例外?
如果您使用不同的字段,有人能解释应该返回什么吗


谢谢。

事实上,这不是100%的时间吗?是否存在这样的情况:您可以在select中有一个不在GROUP BY中的(非聚合)列


但是我没有答案。对于这种语言来说,这确实是一个尴尬的时刻。

因为它们是两个不同的东西,所以您可以按select子句中没有的项目进行分组

编辑:

另外,做出这样的假设安全吗

我有一个SQL语句

Select ClientName, InvAmt, Sum(PayAmt) as PayTot
服务器假设我想按ClientName和InvoiceAmount分组,这是否“正确”? 我个人更喜欢(并且认为这样更安全)使用此代码

Select ClientName, InvAmt, Sum(PayAmt) as PayTot
Group By ClientName
抛出错误,提示我将代码更改为

Select ClientName, Sum(InvAmt) as InvTot, Sum(PayAmt) as PayTot
Group By ClientName

我希望/期望我们很快会看到更全面的东西;关于这一主题的SQL历史课程将非常有用,而且内容丰富。任何人任何人布勒

同时,我可以观察到以下情况:

SQL早于DRY原则,至少在本文中有记载

并非所有的数据库都需要完整的列表:例如,Sybase很乐意执行如下查询

SELECT a, b, COUNT(*)
FROM some_table
GROUP BY a

。。。这(至少每次我无意中运行这样一个怪物时)通常会导致如此巨大的意外记录集,导致惊慌失措的请求很快接踵而至,请求DBA跳出服务器。结果是一种部分笛卡尔积,但我认为这可能主要是Sybase未能正确实现SQL标准。

我倾向于同意您的看法-这是SQL应该有稍微智能化的默认值以节省我们所有人一些输入的许多情况之一。例如,假设这是合法的:

Select ClientName, InvoiceAmount, Sum(PaymentAmount) Group By *
其中“*”表示“所有非聚合字段”。如果每个人都知道它是如何工作的,那么就不会有混乱。如果你想做一些棘手的事情,你可以在一个特定的字段列表中加入子字段,但是splat的意思是“全部”(在这个上下文中是指所有可能的字段)

诚然,“*”在这里的含义与SELECT子句中的含义不同,因此可能使用不同的字符会更好:

Select ClientName, InvoiceAmount, Sum(PaymentAmount) Group By !

在其他一些类似的领域,SQL并不像它可能的那样雄辩。但是在这一点上,它可能太根深蒂固了,无法做出如此大的更改。

这样做的好理由是,如果不指定所有列,您会经常得到错误的结果。假设有三列,
col1
col2
col3

假设您的数据如下所示:

Col1  Col2 Col3
a      b    1
a      c    1
b      b    2
a      b    3
按col1、col2从mytable组中选择col1、col2、sum(col3)

将得出以下结果:

Col1  Col2 Col3
a      b    4
a      c    1
b      b    2
它将如何解释
按col1从mytable组中选择col1、col2、sum(col3)

我猜是

Col1  Col2 Col3
a      b    5
a      c    5
b      b    2
这些显然是糟糕的结果。当然,查询越复杂,连接越多,查询返回正确结果的可能性就越小,或者程序员甚至不知道结果是否不正确


就我个人而言,我很高兴“分组依据”需要字段。

我同意op的观点,即重复有点烦人,特别是如果非聚合字段包含诸如ifs和函数等复杂语句以及大量其他内容。如果GROUPBY子句中可以有一些速记,至少可以有一个列别名,那就太好了。按编号引用列可能是另一种选择,尽管可能有其自身的问题

也许我们需要一个速记表格——称之为GroupSelect

GroupSelect Field1, Field2, sum(Field3) From SomeTable Where (X = "3")

这样,如果您遗漏了聚合函数,解析器只需抛出一个错误。

可能会出现这样的情况,您需要提取所有分组行的一个id,以及它们的数量总和,例如。在这种情况下,您可以按名称对它们进行分组,而不将ID分组。SQLite似乎是这样工作的。

我同意大家分组、分组*或类似的说法。正如在原始帖子中提到的,在99%(可能更多)的情况下,您希望按所有非聚合列/表达式进行分组

然而,这里有一个例子,出于向后兼容性的原因,您需要按列分组

SELECT 
  MIN(COUNT(*)) min_same_combination_cnt, 
  MAX(COUNT(*)) max_same_comb_cnt, 
  AVG(COUNT(*)) avg_same_comb_cnt, 
  SUM(COUNT(*)) total_records,
  COUNT(COUNT(*)) distinct_combinations_cnt
FROM <some table>
GROUP BY <list of columns>
选择
最小(计数(*)最小相同组合,
最大值(计数(*)最大值相同,
平均值(计数(*)平均值相同,
总计(计数(*)总记录,
计数(计数(*)不同的组合
从…起
分组
这在Oracle中起作用。我用它来估计色谱柱的选择性。group by应用于内部聚合函数。然后,应用外部骨料


对于SQL标准的这种改进,最好提出一个建议。我只是不知道它是如何工作的。

因为group by导致整个元组只有一个元组,所以其他非group by属性只能在聚合函数中使用。如果在select中添加非group by属性,则sql无法决定从该组中选择哪个值

确实如此,但是如果选择列表中的列是必需的,那么为什么需要这些列呢<代码>从t组中按b选择a,最大(c)可能意味着按a分组,不是吗?我认为这可能只是一个清晰的问题。隐含操作是调试和测试的祸根。是的。非常感谢。那种事听起来很有道理。我猜答案是“没有真正的