【问题标题】:Transform query that works in SQLite into something that works in Postgres将 SQLite 中的查询转换为 Postgres 中的查询
【发布时间】:2015-08-06 09:30:50
【问题描述】:
Message.order("created_at DESC").where(user_id: current_user.id).group(:sender_id, :receiver_id).count

适用于我的开发环境 SQLite3,用于 Rails 3.2 应用程序,但在使用 Postgres 推送到 Heroku 时失败,并出现以下错误:

PG::GroupingError: ERROR: column "messages.created_at" must appear in the GROUP BY clause or be used in an aggregate function

它似乎在查询中需要:created_at。什么都想不出来。有什么想法吗?

谢谢

【问题讨论】:

  • 您是否尝试根据查询添加 :created_at ? Message.order("created_at DESC").where(user_id: current_user.id).group(:sender_id, :receiver_id, :created_at).count
  • @hd1:虽然这将使 Postgre 接受查询,但结果可能不是预期的:从用户 1 到用户 2 的 2 条消息不会被组合在一起,除非它们是在确切的时间,这不太可能(而且可能不是想要的行为)。
  • 对以上两个 cmets 都是。添加 :created_at 将使查询适用于 Postgres,但结果不正确。实际上,它不再分组,因为每条消息都有一个唯一的 :created_at 列。
  • @slindsey3000:我在下面发布的答案对您不起作用吗?
  • 我正在等待我网站上的流量减少一点,先生,然后将其推向生产。我必须有一个 Rails.env 标志,因为我在本地运行 SQLite。会建议。谢谢你,先生。希望它有效!

标签: ruby-on-rails postgresql heroku sqlite


【解决方案1】:

PostgreSQL 无法弄清楚如何通过您的created_at 订购。

假设您找到两组(:sender_id, :receiver_id),例如[1, 2]
[1, 3]
现在假设在第一组中有 2 条消息,一条来自 1 天前,一条来自 1 分钟前。假设您在 12 小时前的第二组中有 1 条消息。
那么ORDER BY created_at DESC 没有任何意义:您是否将 1 天前的消息作为第一组的 created_at(因此第一组出现在第二组之后),还是 1 分钟前的消息(在在哪种情况下第一组现在首先出现)?

这就是为什么 PostgreSQL 说您需要在 GROUP BY 中拥有 created_at(在这种情况下,您现在有 3 个不同的组,因为第一个组现在被分成两部分),或者您需要使用聚合函数将created_at 的多个值转换为单个值。


这将运行(我不知道您期望的结果是什么,您可能不想使用 MAX(created_at) !您可以找到 PostgreSQL 的 聚合函数列表 here) :

Message.order("MAX(created_at) DESC")
       .where(user_id: current_user.id)
       .group(:sender_id, :receiver_id)
       .count

【讨论】:

  • 工作。谢谢你,先生。完美。
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
相关资源
最近更新 更多