为什么SQL Server在按主键分组时需要聚合函数?

时间:2015-07-07 20:29:58

标签: sql sql-server

假设我有两张桌子

CREATE TABLE users ( name VARCHAR(50) PRIMARY KEY, gender INTEGER );
CREATE TABLE likes ( username VARCHAR(50), object VARCHAR(50) );

现在,我想找出每个用户的性别和喜欢的次数

SELECT 
    u.name, u.gender, COUNT(*) 
FROM users u
INNER JOIN likes l ON u.name = l.username
GROUP BY u.name

这里我按主键分组,这意味着每个组只有一个用户行。但是,SQL Server给出了以下错误

  

列'users.gender'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

为什么抱怨?有没有办法可以达到预期的行为?

编辑:显然,必须将没有聚合函数的所有列添加到GROUP BY子句中。我想真正的问题是:它为什么会这样?

2 个答案:

答案 0 :(得分:2)

您描述的行为实际上与ANSI标准一致。如果一组列定义了一个唯一的行,那么其他值是"功能相关的"在那些专栏上。他们没有其他价值观。这些其他列可以包含在select中,而不会将其包含在group by

识别和实施功能依赖关系的方式是通过主键和唯一键。

所以,你只想包括name的愿望是非常合理的。 SQL Server - 以及大多数其他数据库不支持此功能(我认为该功能对于ANSI兼容性是可选的)。自9.1版以来,Postgres一直支持功能依赖。 MySQL正在修复"他们目前的group by在5.7中支持这一点。

答案 1 :(得分:1)

索引和约束不会影响您可以编写的有效查询。这将需要可能的逻辑推断,但不需要在标准中,而不是在SQL Server中。

实际上,优化器会做所有这些推断。该计划根本不会有任何汇总。这是一个语言设计问题,他们可以理解地选择不允许这样做。它会导致脆弱的查询,并且几乎不会给客户带来任何好处。