atm*_*ell 8 ruby postgresql ruby-on-rails
我正在尝试加载由user_id分组并由created_at排序的最新10种艺术.这适用于SqlLite和MySQL,但在我的新PostgreSQL数据库上出错.
Art.all(:order => "created_at desc", :limit => 10, :group => "user_id")
Run Code Online (Sandbox Code Playgroud)
ActiveRecord错误:
Art Load (18.4ms) SELECT "arts".* FROM "arts" GROUP BY user_id ORDER BY created_at desc LIMIT 10
ActiveRecord::StatementInvalid: PGError: ERROR: column "arts.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "arts".* FROM "arts" GROUP BY user_id ORDER BY crea...
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
表达式生成的sql不是一个有效的查询,你正在分组user_id并根据它选择很多其他字段,但不告诉DB它应该如何聚合其他文件.例如,如果您的数据如下所示:
a | b
---|---
1 | 1
1 | 2
2 | 3
Run Code Online (Sandbox Code Playgroud)
现在,当您要求db分组a并返回b时,它不知道如何聚合值1,2.你需要告诉它是否需要选择最小值,最大值,平均值,总和或其他东西.正如我在写答案时,有两个答案可以更好地解释这一切.
但是在你的用例中,我认为你不希望在db级别上有一个组.由于只有10种艺术,您可以将它们分组在您的应用程序中.不要将这种方法用于成千上万的艺术:
arts = Art.all(:order => "created_at desc", :limit => 10)
grouped_arts = arts.group_by {|art| art.user_id}
# now you have a hash with following structure in grouped_arts
# {
# user_id1 => [art1, art4],
# user_id2 => [art3],
# user_id3 => [art5],
# ....
# }
Run Code Online (Sandbox Code Playgroud)
编辑:选择latest_arts,但每个用户只有一个艺术品
只是为了给你一个sql的想法(没有测试它,因为我没有在我的系统上安装RDBMS)
SELECT arts.* FROM arts
WHERE (arts.user_id, arts.created_at) IN
(SELECT user_id, MAX(created_at) FROM arts
GROUP BY user_id
ORDER BY MAX(created_at) DESC
LIMIT 10)
ORDER BY created_at DESC
LIMIT 10
Run Code Online (Sandbox Code Playgroud)
这个解决方案基于实际的假设,即同一个用户的两个艺术没有同样最高的created_at,但如果你是导入或编程创建大量的艺术,那么它可能是错误的.如果假设不成立,那么sql可能会更加有条理.
编辑:尝试将查询更改为Arel:
Art.where("(arts.user_id, arts.created_at) IN
(SELECT user_id, MAX(created_at) FROM arts
GROUP BY user_id
ORDER BY MAX(created_at) DESC
LIMIT 10)").
order("created_at DESC").
page(params[:page]).
per(params[:per])
Run Code Online (Sandbox Code Playgroud)
您需要选择所需的特定列
Art.select(:USER_ID).集团(:USER_ID).limit(10)
例如,当您尝试在查询中选择标题时,它会引发错误
Art.select(:user_id,:title).group(:user_id).limit(10)
列"arts.title"必须出现在GROUP BY子句中或用于聚合函数
这是因为当您尝试按user_id分组时,查询不知道如何处理组中的标题,因为该组包含多个标题.
所以异常已经提到你需要出现在group by中
Art.select(:user_id,:title).group(:user_id,:title).limit(10)
或用于聚合函数
Art.select("user_id,array_agg(title)as titles").group(:user_id).limit(10)
| 归档时间: |
|
| 查看次数: |
9170 次 |
| 最近记录: |