在 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 或任何其他数据库中不支持您要求的内容。某些数据库支持功能依赖,但它们会查看表的定义以查看值是否必须相关(即 column1
是 unique
)。他们不检查数据在其他情况下是否具有唯一值。
一般的 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 特定列不需要聚合函数?的主要内容,如果未能解决你的问题,请参考以下文章