我有这个查询在MySQL中正常工作。更多背景信息here。
SELECT c.*, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
WHERE c.id = i.category_id
AND i.id = v.voteable_id
AND v.created_at > '#{1.week.ago}'
GROUP BY c.id
ORDER BY score DESC LIMIT 8;
我尝试在PostgreSQL中运行它,但它失败并出现此错误消息。
PGError:错误:列“c.name”必须 出现在GROUP BY子句中或是 用于聚合函数
我不确定这是什么意思,所以我尝试在group by子句中将“c.id”更改为“c.name”(假设项目的名称是唯一的,两者在MySQL中的工作方式相同)。
然而,这只是产生了另一个类似的错误
PGError:错误:列“c.id”必须 出现在GROUP BY子句中或是 用于聚合函数
如何解决这个问题?
答案 0 :(得分:11)
您必须列出要分组的SELECT中的列名称:
SELECT c.id, c.name, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
WHERE c.id = i.category_id
AND i.id = v.voteable_id
AND v.created_at > '#{1.week.ago}'
GROUP BY c.id, c.name
ORDER BY score DESC LIMIT 8;
“不允许在SELECT子句中包含未在GROUP BY子句中引用的列名。”
答案 1 :(得分:8)
我刚刚遇到这个问题但是从MySQL到SQL Server。我认为这是允许的,这很奇怪!
是的,在大多数数据库中,当您拥有GROUP BY子句时,您只能选择GROUP BY子句中出现的列或列的聚合。这是因为它无法知道您选择的其他列是否真正独一无二。
如果它们确实是唯一的,只需将所需的列放在GROUP BY中即可。这是MySQL的一个“功能”,值得怀疑。
您可以阅读有关MySQL的行为及其与here的不同之处。
示例:
SELECT c.*, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
WHERE c.id = i.category_id
AND i.id = v.voteable_id
AND v.created_at > '#{1.week.ago}'
GROUP BY c.id, c.name, c.whatever_else
ORDER BY score DESC LIMIT 8;
答案 2 :(得分:2)
如果您将声明更改为此声明,则应该有效:
SELECT c.id, SUM(ABS(v.vote)) AS score
FROM categories c,items i, votes v
WHERE c.id = i.category_id
AND i.id = v.voteable_id
AND v.created_at > '#{1.week.ago}'
GROUP BY c.id
ORDER BY score DESC LIMIT 8;
我不确定MySQL会给出什么结果,但是为了给出一个很小的例子,说明为什么这在PostgreSQL中不起作用,请看看下面的categories
表:
id | name
---|-----
1 | ABC
1 | DEF
您按id
进行分组,因此结果中的每一行只应包含一个id
。如果您也选择了name
,而没有按其分组,那么name
的结果应该显示什么?
它可以是ABC
或DEF
,但数据库引擎无法真正为您决定(尽管MySQL显然可以)。