在 Postgresql 中选择带有计数的数据

Posted

技术标签:

【中文标题】在 Postgresql 中选择带有计数的数据【英文标题】:Select Data with Count in Postgresql 【发布时间】:2020-05-08 09:03:41 【问题描述】:

我想问如何选择数据和计数数据。

在这种情况下,我希望用户出现以及他拥有的交易数量。

喜欢我制作的这段代码。

SELECT "transaction"."user_id",
COUNT(transaction.id) trans_count
FROM transaction 
inner join "users" on "users"."id" = "transaction"."user_id"
GROUP BY user_id

上面的代码成功选择了user_idtrans_count,但是当我试图显示users.name

出现此错误消息。

查询错误:错误:列“users.name”必须出现在 GROUP BY 子句或用于聚合函数第 3 行:"users"."name"

是我统计数据时无法选择其他数据还是有更好的方法?

谢谢。

【问题讨论】:

当涉及多个表时,对所有列进行限定是一种很好的编程习惯,例如"transaction"."user_id" 您通常 GROUP BY 与您 SELECT 相同的列,除了那些作为设置函数的参数的列。 我认为不需要 group by 来呼叫其他人。谢谢你很有帮助 【参考方案1】:

您可以在group by 中包含user.name

SELECT "transaction"."user_id",
"user"."name",
COUNT(transaction.id) trans_count
FROM transaction 
inner join "users" on "users"."id" = "transaction"."user_id"
GROUP BY "transaction"."user_id", "user"."name"

否则,当 DBMS 尝试将 (group) 多行合并为一行时,它不知道应该选择哪个 name 值,这就是它抛出错误的原因。

在这种情况下,user_iduser.name 具有一对一的映射关系,因此您只需在 group by 子句中包含 name

否则您必须告诉 DBMS 如何从每个组中的多条记录中选择一个值,例如:

min(user.name)max(user.name)

SELECT "transaction"."user_id",
min("user"."name") user_name,
COUNT(transaction.id) trans_count
FROM transaction 
inner join "users" on "users"."id" = "transaction"."user_id"
GROUP BY "transaction"."user_id"

【讨论】:

谢谢你的解释我明白了,现在可以了! :)【参考方案2】:

当您使用GROUP BY 您必须按正在获取或使用聚合函数的所有列分组

分组依据(与@rohitvats 相同)

GROUP BY "transaction"."user_id", "user"."name"

---- 或 ----

聚合函数MAX()MIN()

SELECT "transaction"."user_id",
MAX("user"."name") as name,
COUNT(transaction.id) trans_count
FROM transaction 
inner join "users" on "users"."id" = "transaction"."user_id"
GROUP BY "transaction"."user_id"

【讨论】:

这很有帮助,之后我会进一步了解你的意思。【参考方案3】:

如果您通过users.id 聚合,您的代码将可以工作

SELECT u.id, u.user_name, COUNT(*) as trans_count
FROM users u JOIN
     transaction t
     ON t.id = u.user_id
GROUP BY u.id;

(我删除了双引号,因为它们使逻辑混乱,没有必要解释发生了什么。)

为什么?据推测,users.id 是唯一的(或等效的主键)。 Postgres 支持通过表中的唯一键进行聚合,还支持在SELECT 中包含未聚合的列。这是 SQL 标准中“功能相关”聚合的实现。

当您使用transactions.user_id 时,Postgres 无法识别功能依赖(即使您可能认为ON 子句会暗示它)。所以,你的代码不起作用。

另一种方法是将user_name 也添加到GROUP BY。但是,如果您使用正确表中的列,您的版本几乎可以工作。

【讨论】:

就这样吧。谢谢你的解释很容易理解。 :)

以上是关于在 Postgresql 中选择带有计数的数据的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql 选择计数查询需要很长时间

PostgreSQL - 带有错误计数输出的左连接

从 PostgreSQL 中的字段中提取数字

如何删除或更改postgresql上的cakephp分页计数查询?

JOOQ - 在选择查询中选择计数

带有sails.js 和sails-postgresql 的数据库模式