【问题标题】:Converting MySQL select to PostgreSQL将 MySQL 选择转换为 PostgreSQL
【发布时间】:2011-03-30 00:18:28
【问题描述】:

我有这个在 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 子句中或被 在聚合函数中使用

如何解决这个问题?

【问题讨论】:

  • 奇怪的是,现在 Postgre 9.1 似乎允许这样做
  • 它在 Postgre 9.2 中被删除了吗?出于同样的原因,我收到此错误。
  • @Aaron:它没有被删除,但仅在(引用documentation)时起作用:未分组的列在功能上依赖于分组的列,否则可能会有多个为未分组的列返回的值。如果分组列(或其子集)是包含未分组列的表的主键,则存在函数依赖关系

标签: mysql sql postgresql


【解决方案1】:

您必须在 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 子句中引用的列名。”

【讨论】:

  • 在 MySQL 中是允许的,这就是他感到困惑的原因。我认为可怕的功能
【解决方案2】:

我刚刚遇到了这个问题,但是从 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;

【讨论】:

  • 感谢 MySQL 链接,它现在更有意义了!在这种情况下,我的 c.id 始终是唯一的,所以它可能没问题,但至少我现在知道他们为什么这样做了。谢谢!
【解决方案3】:

如果你把你的陈述改成这样,它应该可以工作:

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 显然可以)。

【讨论】:

  • MySQL 随机选择一个!是不是很奇怪?几天前我问了一个关于这个的问题。
  • 有趣...在这种情况下,至少我的 id 始终是唯一的,因此它是一个很好的分组依据。我也需要类别的名称,所以我只在 select 和 group by 中列出。似乎工作。谢谢!
猜你喜欢
  • 2021-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-05
  • 1970-01-01
相关资源
最近更新 更多