为什么按主键分组时可以选择所有字段,而按另一列分组时却不能选择所有字段

Sac*_*rma 7 postgresql select group-by

这是如何有效的语句(其中 id 是表的主键):

select * from table group by id ;
Run Code Online (Sandbox Code Playgroud)

这不是:

select * from table group by name ;
Run Code Online (Sandbox Code Playgroud)

错误:列“pgluster.id”必须出现在 GROUP BY 子句中或用于聚合函数中

小提琴

问题是为什么第一个是合法查询,即为什么按主键分组是有效的?

Dav*_*itz 9

id是主键。
据我所知,这实际上是根据 ANSI/ISO SQL 的合法查询。
按主键分组会导致每个组中的单个记录在逻辑上与根本不分组/按所有列分组相同,因此我们可以选择所有其他列。

create table t (id int primary key,c1 int,c2 int)
insert into t (id,c1,c2) values (1,2,3),(4,5,6);
select * from t group by id;
Run Code Online (Sandbox Code Playgroud)
+----+----+----+
| id | c1 | c2 |
+----+----+----+
| 1  | 2  | 3  |
+----+----+----+
| 4  | 5  | 6  |
+----+----+----+
Run Code Online (Sandbox Code Playgroud)

@a_horse_with_no_name 给出的参考

https://www.postgresql.org/docs/current/static/sql-select.html#SQL-GROUPBY

当存在 GROUP BY 或存在任何聚合函数时,SELECT 列表表达式引用未分组的列是无效的,除非在聚合函数内或当未分组的列在功能上依赖于分组的列时,否则会有更多为未分组的列返回一个可能的值。如果分组列(或其子集)是包含未分组列的表的主键,则存在函数依赖性。


虽然从逻辑上讲,我们希望 UNIQUE NOT NULL 遵循相同的行为,但它仅适用于 PK(如文档中所述)

create table t (id int unique not null,c1 int,c2 int);
insert into t (id,c1,c2) values (1,2,3),(4,5,6);
select * from t group by id;
Run Code Online (Sandbox Code Playgroud)

[代码:0,SQL 状态:42803] 错误:列“t.c1”必须出现在 GROUP BY 子句中或用于聚合函数中