我在Postgres中遇到此代码时遇到问题。我想获取用户表中的所有字段,但只能按ID分组。这适用于MySQL和SQLite,但在谷歌搜索后我发现这种行为不是标准的一部分。
SELECT u.*, p.*, count(o.id) AS order_count
FROM shop_order AS o
LEFT JOIN user AS u ON o.user_id = u.id
LEFT JOIN userprofile AS p ON p.user_id = u.id
WHERE o.shop_id = <shop_id>
GROUP BY u.id
(请注意,<shop_id>
正在以编程方式传递,因此您可以轻松地将其替换为任何整数。)
这是我得到的错误
column "u.id" must appear in the GROUP BY clause or be used in an aggregate function
我是一个SQL新手,如果这很明显,请保持温和:)
答案 0 :(得分:3)
不幸的是,如果不列出user
和userprofile
中的所有列,我认为您无法做到这一点。 (通常认为使用通配符只是为简单的即席查询做的事情,我想这也是原因之一!)MySQL和其他数据库有一个“方便”的功能,即如果一个列既不在GROUP中BY子句或聚合函数中,每个组中该列的任何值都可以显示在结果中。 PostgreSQL有点严格。
但通常情况下,只有表中的几列足以进行分组。有很多方法可以重写它。也许你能做的就是:
SELECT u.*, p.*, (select count(o.id) FROM shop_order AS o WHERE o.user_id = u.id AND o.shop_id = <shop_id>) AS order_count
FROM user AS u
LEFT JOIN userprofile AS p ON p.user_id = u.id
答案 1 :(得分:2)
您可以使用row_number
将结果限制为每个用户一行:
select *
from (
select row_number() over (partition by u.id) as rn
, *
join user u
on sub.user_id = u.id
join shop_order so
on so.user_id = u.id
left join
userprofile up
on up.user_id = u.id
where so.shop_id = <shop_id>
) as SubQueryAlias
where rn = 1
子查询是必需的,因为Postgres不允许row_number
子句中的where
等窗函数。
答案 2 :(得分:2)
您正在尝试要求数据库计算一些非常不具体的内容 您想要计算订单,但是您想要显示所有详细信息,如果用户配置文件包含每个用户多行并且这些行不同,那么每个u.id将为您指定多行你只想要一个 这就是为什么数据库在说&#34;走开,告诉我你真正想要的东西&#34;
答案 3 :(得分:2)
你的Postgres版本是什么?如果您使用的是Postgres 9.0及更低版本,则代码构造将无法运行。例如这是不允许的:
SELECT
p.id,
p.firstname, p.lastname, p.address, -- these auxiliary fields is helpful to program users
count(*)
FROM
people p
JOIN visits v ON p.id = v.person_id
GROUP BY p.id
必须在9.0及以下版本中执行此操作:
SELECT
p.id,
p.firstname, p.lastname, p.address, -- these auxiliary fields is helpful to program users
count(*)
FROM
people p
JOIN visits v ON p.id = v.person_id
GROUP BY p.id
,p.firstname, p.lastname, p.address; -- these ancillary fields aids the RDBMS on preventing
-- programmers from accidentally committing the same mistake as MySQL programmers.
如果你正在使用Postgres 9.1,你肯定只能在GROUP BY中使用一个字段,即使你在SELECT子句中有很多字段,只要该GROUPed字段是主键即可。因此,这将运行:
SELECT
p.id,
p.firstname, p.lastname, p.address, -- these auxiliary fields is helpful to program users
count(*)
FROM
people p
JOIN visits v ON p.id = v.person_id
GROUP BY p.id
-- note that there's no need to repeat the SELECTed fields on GROUP BY clause
Postgres 9.1可以促进functional dependencies on primary keys,因此只允许包含GROUP BY子句的主键
SQL小提琴示例:http://sqlfiddle.com/#!1/3b857/3
答案 4 :(得分:1)
您正在使用哪个版本的PostgreSQL?我相信它是9.1之前的一个。
Starting from version 9.1如果您执行GROUP BY
主键列,PostgreSQL也支持您正在寻找的功能。所以升级可能是一个很好的选择。