在 group by 中,有没有办法告诉 SQL 特定列不需要聚合函数?

Posted

技术标签:

【中文标题】在 group by 中,有没有办法告诉 SQL 特定列不需要聚合函数?【英文标题】:In a group by, is there a way to tell SQL no aggregate function should be needed for a specific column? 【发布时间】:2020-03-02 19:51:37 【问题描述】:

我最近开始使用 T-SQL,但遇到了按功能分组的问题。

假设我有一个包含 3 列的表:Column_1、Column_2 和 Column_3。我知道对于 Column_1 的给定值,Column_2 将始终具有给定值。另一方面,Column_3 独立于 Column_1。

所以表格应该是这样的:

Column_1    Column_2    Column_3 
1           42          57 
1           42          35 
2           3           5
2           3           6 
5           78          45 

我想对 Column_1 进行分组以聚合 Column_3(假设使用 sum())。但是,当我进行分组时,即使我知道没有必要,我也必须分组或聚合 Column_2。

所以我的 SQL 请求是:

select Column_1, Column_2, sum(Column_3) 
from Table 
group by Column_1, Column_2

select Column_1, max(Column_2), sum(Column_3) 
from Table 
group by Column_1
(using max as a workaround to avoid grouping by Column_2)

我的问题是:有没有办法告诉 SQL Column_2 不需要聚合函数并让 SQL 检查假设是否正确?

我认为这是一个最佳选择,因为它使我能够确定我的假设是正确的。在使用前两个请求时,我永远不能 100% 确定是这种情况(除非我在请求之前以另一种方式检查它)并且可能会导致难以识别的错误(尤其是在使用最大解决方法时)。

理想情况下,我希望能够写出类似的东西:

select Column_1, no_agg_necessary(Column_2), sum(Column_3) 
from Table 
group by Column_1

如果 Column_2 值在按给定 Column_1 值分组时不相同,则会出现警告。

我在想这样的事情来选择 Column_2 可以满足我的需要:

case when count(distinct Column_2) = 1 then max(Column_2) else raiseerror() end as Column_2

但是在这种情况下似乎不可能使用 raiseerror() 并且添加 distinct 会减慢请求。

您知道任何可以满足我需求的 SQL 功能吗?

【问题讨论】:

【参考方案1】:

您的示例数据缺少“问题”

如果我添加行,您将如何处理查询

1 - 41 - 19

您现在对该列有多个值。期望结果如何?

41? 42? “无效”?

因此,为了保持数据正确,您最有可能需要将其分成 2 个结果记录,您可以通过将其添加到 group 子句来实现。

如果你不太关心数据,你可以使用像 min() 或 max() 之类的虚拟函数,或者如果你想在 Min() 时注入一个“无效”值 最大值()

【讨论】:

在您添加的行的情况下,我希望结果返回错误,因为据我了解,该表不应该以可能存在该行的方式构建。因此,如果我的假设是错误的(或者如果表包含错误,或者如果表由于某种原因及时演变),我希望对该假设进行查询并得到错误。 好吧,这个错误让事情变得更难......你需要一个真正的例外,或者像“ERR”这样的标签可以吗?如果标签没问题,您可以使用 IF 来比较 min(field) 和 max(field) - 如果它们彼此偏离输出 err 如果不只是使用 min 或 max... 感谢您的回答。我想我会接受 Gordon 的建议,即数据应该在所需查询之前的单独步骤中进行验证。正如你们都指出的那样,通过比较最小值和最大值可以获得错误标签,这是我没有想到的。但是,这意味着必须在之后检查标签是否存在,所以我不妨事先验证数据,因为我必须在两种情况下都验证! 如果你说“不可能发生”,你可以考虑在表上添加一个唯一索引来执行它。这样就不能输入错误的数据,也不需要在查询时检查【参考方案2】:

在 SQL Server 或任何其他数据库中不支持您要求的内容。某些数据库支持功能依赖,但它们会查看表的定义以查看值是否必须相关(即 column1unique)。他们不检查数据在其他情况下是否具有唯一值。

一般的 SQL(尤其是 SQL Server)并不特别擅长在 SELECT 语句中生成错误。可以使用CASE 表达式。在非聚合查询中,SQL Server 保证评估顺序,甚至在编译阶段不评估错误。

所以,你可以写下你想要的:

select x,
       (case when min(y) = max(y)
             then min(y) else convert(int, 'Bad column value')
        end)
from (values (1, 1), (1, 1), (1, 2)) v(x, y)
group by x;

我真的不建议以这种方式处理查询。您应该将数据验证作为一个单独的步骤,这样您就不会对得到的结果感到惊讶。

【讨论】:

以上是关于在 group by 中,有没有办法告诉 SQL 特定列不需要聚合函数?的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 中执行 GROUP BY 后计算记录数

group by 优化大法

mysql出现GROUP BY clause错误解决办法

不是group by 表达式

SQL里面group by 语句和WHERE的区别,高手进

Mysql5.7中子查询时order by与group by合用无效的解决办法