将MySQL select转换为PostgreSQL

时间:2009-06-30 07:07:28

标签: mysql sql postgresql

我有这个查询在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子句中或是   用于聚合函数

如何解决这个问题?

3 个答案:

答案 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的结果应该显示什么?

它可以是ABCDEF,但数据库引擎无法真正为您决定(尽管MySQL显然可以)。