Postgresql“列必须出现在 GROUP BY 子句中或在聚合函数中使用”和唯一字段
Posted
技术标签:
【中文标题】Postgresql“列必须出现在 GROUP BY 子句中或在聚合函数中使用”和唯一字段【英文标题】:Postgresql "column must appear in the GROUP BY clause or be used in an aggregate function" and unique field 【发布时间】:2021-03-05 06:39:20 【问题描述】:我知道这个问题被问了很多,但我没有找到关于为什么我收到这个带有唯一字段的错误消息的答案:
这是我的 2 个表和一个索引:
CREATE TABLE posts (
id bigint NOT NULL,
user_id bigint NOT NULL,
content text
);
CREATE TABLE users (
id bigint NOT NULL,
email character varying DEFAULT ''::character varying NOT NULL
)
CREATE UNIQUE INDEX index_users_on_email ON users USING btree (email);
以下sql请求:
SELECT posts.content, users.email /*, other aggregate fields not relevant for the question */
FROM posts
INNER JOIN users ON posts.user_id = users.id
/* Other `inner join`s but not relevant for the question */
GROUP BY posts.id;
给我错误column "users.email" must appear in the GROUP BY clause or be used in an aggregate function
。
但是电子邮件字段是唯一的(如果它改变了任何东西)并且帖子只能有一个用户(所以一封电子邮件)。
我不明白为什么此请求无效,因为每个 post
不可能有多个 email
值。
【问题讨论】:
更大的问题是为什么在你从不选择任何聚合函数的情况下首先使用GROUP BY
。也许您可以在此处描述您希望查询执行的操作。
请求已被减轻以关注错误部分。当然,它做的事情比现实中的要多。但我想了解为什么这部分无效。
给定帖子的内容可能有多个关联的用户电子邮件。请记住,即使关系真的是一对一的,Postgres 也不知道这一点。
我不知道为什么。 users.id
也是独一无二的,所以我想不出一个帖子可以有多个用户的方法。几年来我在不同的请求中看到了这个错误,所以我有点沮丧,不能正确理解它:D
重点是:尽管可能是一对一的,但 Postgres 并不知道这一点。作为参考,您的查询将在关闭ONLY_FULL_GROUP_BY
模式的 mysql 上运行而不会出现错误(并且具有正确的预期结果集)。
【参考方案1】:
您需要将用户表的主键添加到group by
子句中,以使查询成为有效的聚合查询:
SELECT p.content, u.email /*, other aggregate fields not relevant for the question */
FROM posts p
INNER JOIN users u ON p.user_id = u.id
/* Other `inner join`s but not relevant for the question */
GROUP BY posts.id, u.id;
Postgres 在函数依赖方面非常聪明,但不是那么聪明。它了解功能相关列的概念,但不了解跨表。即使您设置了正确的外键,它也无法预见 post
唯一地引用用户。我不认为这样的东西是在标准 ANSI SQL 中定义的。
【讨论】:
以上是关于Postgresql“列必须出现在 GROUP BY 子句中或在聚合函数中使用”和唯一字段的主要内容,如果未能解决你的问题,请参考以下文章
prometheus使用postgresql-adapter连接postgresql
PostgreSQL介绍以及如何开发框架中使用PostgreSQL数据库