为何Redshift要求所有非聚合列必须包含在GROUP子句中?
为什么Redshift要求所有非聚合列必须包含在GROUP子句中?
这个问题问到了点子上,核心差异其实在于SQL标准的遵循程度,以及不同数据库的设计定位:
1. 先明确SQL标准的硬性规定
SQL官方标准里明确要求:当使用GROUP BY进行分组聚合时,SELECT子句中出现的非聚合函数包裹的列,必须全部出现在GROUP BY的分组列表里。
原因很直白:分组后,每个组是一组行的集合,如果某个非聚合列不在GROUP BY里,数据库根本无法确定要返回这个组里哪一行的该列值——这是逻辑上的歧义,标准SQL绝不允许这种模糊的查询逻辑。
2. MySQL的“特殊”非标准实现
你例子里MySQL允许SELECT sum(x),y,z FROM sample group by z这种写法,其实是MySQL默认开启了非标准的宽松模式。它会随机选取组内某一行的对应列值返回,但这个结果是不确定的:不同版本、不同执行计划下,返回的y值可能不一样(比如你的例子里返回了3,但换个场景可能返回2),这在严谨的数据查询场景下是很危险的。
如果你给MySQL开启sql_mode=ONLY_FULL_GROUP_BY这个严格模式,它也会像Redshift一样报错,强制要求非聚合列必须出现在GROUP BY里。
3. Redshift遵循标准的原因
Redshift是面向数据仓库的OLAP系统,它的设计定位是处理大规模、严谨的数据分析需求,所以严格遵循SQL标准:
- 避免不确定结果:强制要求分组列完整,保证查询结果是逻辑确定的,不会出现随机返回的情况
- 提前规避逻辑漏洞:数据仓库场景下,用户通常需要明确的分组维度,这种强制要求能帮用户及时发现漏写分组列的错误,避免得到不符合预期的聚合结果
结合你的例子来看:
- 当你执行
SELECT sum(x),y,z FROM sample group by z时,Redshift会报错,因为y不在分组列里,无法确定返回哪个y值 - 而
group by y,z是符合标准的,每个(y,z)组合是唯一的分组,每个组只有一行数据,sum(x)就是该行的x值,结果完全确定
内容的提问来源于stack exchange,提问作者johnnash
相关产品推荐
相关产品推荐

