我有这样的查询:
select foo.*, count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id
这适用于SQLite和MySQL。然而,Postgres抱怨我没有在group by
子句中包含foo的所有列。为什么是这样? foo.id是独一无二的还不够吗?
答案 0 :(得分:31)
以防万一其他人偶然发现这个问题:
从PostgreSQL 9.1开始,在group by子句中列出主键的列就足够了(因此问题中的示例现在可以正常工作)。
答案 1 :(得分:5)
有些数据库对此更加放松,无论好坏。查询是非特定的,因此结果同样不明确。如果数据库允许查询,它将从每个组返回一条记录,而不关心哪一条记录。其他数据库更具体,需要您指定组中所需的值。他们不会让您编写具有非特定结果的查询。
在没有聚合的情况下,您可以选择的唯一值是group by
子句中的值:
select foo.id, count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id
您可以使用聚合来获取其他值:
select foo.id, min(foo.price), count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id
如果你想要foo表中的所有值,你可以将它们全部放在group by
子句中(如果这给出了正确的结果):
select foo.id, foo.price, foo.name, foo.address, count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id, foo.price, foo.name, foo.address
或者,您可以使用子查询加入表:
select foo.id, foo.price, foo.name, foo.address, sub.bar_count
from foo
inner join (
select foo.id, bar_count = count(bar.id)
from foo inner join bar on foo.id = bar.foo_id
group by foo.id
) sub on sub.id = foo.id
答案 2 :(得分:3)
你究竟会有什么postgresql输出?您正在使用聚合函数并尝试输出“某些东西”。
阿。我明白你可能想做什么。使用子选择。
select foo.*, (select count(*) from bar where bar.foo_id=foo.id) from foo;
检查说明该计划看起来不错。一个子选择并不总是坏的。我只是检查了我正在使用的数据库,我的执行计划对该查询很有用。
是的,理论上用foo.id分组就足够了(即:你的查询加上“foo.id分组”)。但显然(我测试过)postgresql不会这样做。另一种选择是“按foo.id,foo.foo,foo.bar,foo.baz分组”以及“foo。*”中的所有其他内容。
Guffa所依据的另一种方式是:
SELECT foo.*, COALESCE(sub.cnt, 0)
FROM foo
LEFT OUTER JOIN (
SELECT foo_id, count(*) AS cnt
FROM bar
GROUP BY foo_id) sub
ON sub.foo_id = foo.id;
这将是两个查询(一个子查询,只运行一次),这可能很重要,但可能不会。如果您可以不使用“foo。*”,则可以使用明确按所有列分组的第二个版本。
答案 3 :(得分:1)
GROUP BY
子句要求查询返回的每一列都是GROUP BY
语句中包含的列或聚合函数(例如示例中的COUNT
)。如果没有看到GROUP BY
子句是什么或foo
的列是什么,很难说出究竟发生了什么,但我猜是问题是foo.*
试图返回一个或多个不在GROUP BY
子句中的列。
这实际上是SQL的一般属性,不应该特定于PostgreSQL。不知道为什么它适用于SQLite或MySQL - 也许foo.*
中的所有列实际上都在你的GROUP BY
子句中但是PostgreSQL无法解决这个问题 - 所以尝试列出所有的明确列foo
。