首页 > 解决方案 > 未在 GROUP BY 原因或聚合函数中选择的列?

问题描述

我有一个数据库catstoys它们之间的关系cat_toys

要查找拥有超过 5 个玩具的猫的名字,我有以下查询:

select
  cats.name
from
  cats
join
  cat_toys on cats.id = cat_toys.cat_id
group by
  cats.id
having
  count(cat_toys.toy_id) > 7
order by
  cats.name

cats.name未出现在聚合函数中group by或未在聚合函数中使用,但此查询有效。相反,我无法选择cat_toys表格中的任何内容。

这是 psql 的特别之处吗?

标签: sqldatabasepostgresqljoingroup-by

解决方案


这是您的查询:

select c.name
from cats c join
     cat_toys ct
     on c.id = ct.cat_id
group by c.id
having count(ct.toy_id) > 7
order by c.name;

您在问它为什么起作用:您正确地观察到c.id它在group by但不在select-- 并且另一select. 似乎错了。但事实并非如此。Postgres 支持标准中鲜为人知的部分,与聚合查询中的功能依赖相关。

让我避免使用技术术语。 cats.id是 的主键cats。这意味着id是唯一的,因此知道id指定来自 的所有其他列cats。数据库知道这一点——它知道 的值name对于给定的 总是相同的id。因此,通过对主键进行聚合,您可以在不使用聚合函数的情况下访问其他列——这与标准一致。

这在文档中进行了解释:

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


推荐阅读