【问题标题】:Grouping and ordering using ActiveRecord Query interface使用 ActiveRecord 查询接口进行分组和排序
【发布时间】:2019-10-13 02:55:00
【问题描述】:

我有一个模型ConnectedUser,它属于另外两个模型UserStation

这是一个只有这些关系和布尔值active 的简单模型。

我要查询的结果将只是每个User 的每个最近的ConnectedUser 记录(其中Station 是一个特定的ID)。

例如,如果我的ConnectedUser 表看起来像这样......

+----+---------+------------+--------+------------+
| id | user_id | station_id | active | created_at |
+----+---------+------------+--------+------------+
|  1 |       1 |          1 | true   | 20 June    |
|  2 |       1 |          1 | false  | 19 June    |
|  3 |       1 |          2 | false  | 20 June    |
|  4 |       2 |          1 | false  | 18 June    |
|  5 |       2 |          1 | false  | 21 June    |
+----+---------+------------+--------+------------+

而车站是 id 为 1 的车站,那么我希望查询返回...

[
<ConnectedUser id: 1, user_id: 1, station_id: 1, active: true, created_at: "2019-06-20">,
<ConnectedUser id: 5, user_id: 2, station_id: 1, active: false, created_at: "2019-06-21">
]

为了实现这一点,我一直在尝试使用grouporder

ConnectedUser.where(station: station).select(:user_id).group(:user_id).order(:created_at)

但不断收到这样的错误:

ActiveRecord::StatementInvalid (PG::GroupingError: ERROR: column “connected_users.created_at”必须出现在 GROUP BY 子句中或 用于聚合函数)

我无法获得特定的ConnectedUser id,所以感觉我缺少一些重要的了解如何使用group 并汇总结果。

这可以在一个 ActiveRecord 查询中实现吗?

非常感谢。

【问题讨论】:

  • 抱歉,它不应该改变,我已经编辑修复它。

标签: ruby-on-rails postgresql activerecord


【解决方案1】:

在 Postgres 中,如果您想要每个用户/站的最新版本,我会推荐 distinct on:

select distinct on (station_id, user_id) cu.*
from ConnectedUser cu
order by station_id, user_id, created_at desc;

【讨论】:

  • 谢谢,如果可能的话,我想使用 ActiveRecord 查询,这样我就可以通过参数传入station
【解决方案2】:

您应该使用DISTINCT ON 而不是GROUP。以下是在 Rails 中执行此操作的方法:

ConnectedUser.select("DISTINCT ON (station_id, user_id) *")
             .where(station_id: params[:station_id])
             .order(created_at: :desc)

当然params[:station_id]是你要过滤的东西

【讨论】:

  • 谢谢,尽管尝试 ConnectedUser.select("DISTINCT ON (station_id, user_id)").where(station: station).order(created_at: :desc) 给我这个错误... ActiveRecord::StatementInvalid (PG::SyntaxError: ERROR: syntax error at or near "FROM") LINE 1: SELECT DISTINCT ON (station_id, user_id) FROM "connected_use...
  • 是的,看来我在选择语句中忘记了字符 *。请查看我更新的答案,看看它现在是否有效
【解决方案3】:

应该可以解决

ConnectedUser.where(active: true).order(user_id: :desc).uniq(&amp;:user_id)

order用于对DESC中的user_id字段进行排序

在这个解决方案中,我使用uniq,它是一个数组解决方案,将只选择最近的user_id

编辑:

我错了,uniq 没有按预期工作,但是在这里测试,我发现:

ConnectedUser.where(active: true).order(created_at: :desc).group(:user_id)

看起来很像你的,但是,当你使用 select 时,它只选择字段 user_id,所以,你不能通过 created_at 订购

应该工作

【讨论】:

  • 谢谢,使用uniq 似乎很有趣,但我认为uniq 现在已被弃用,取而代之的是distinct。尝试它时,它似乎也没有返回最新的记录——但按 created_at 排序似乎没有帮助。
  • 嗨,使用编辑后的版本,我现在又遇到了我一直在尝试解决的熟悉错误:(PG::GroupingError: ERROR: column "connected_users.id" must appear in the GROUP BY clause or be used in an aggregate function) 感谢您的尝试。
  • @Chris,如果您尝试将id 放入组中,例如group(:id, :user_id)
  • 是的,我已经尝试过这种方法及其变体,但没有任何运气。再次感谢。
猜你喜欢
  • 1970-01-01
  • 2010-11-18
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 1970-01-01
  • 1970-01-01
  • 2015-06-23
相关资源
最近更新 更多