我有场地和场地有很多项目。我想获得每个场地的最新项目。要在单个查询中返回每个场地的最新项目,我可以使用max aggregate函数和group by:
class Item < ActiveRecord::Base
scope :newest_items, -> (venue_ids) {
select('max(items.id) as id, venue_id').joins(:venue).where('venues.id IN (?)', venue_ids).group(:venue_id)
}
end
生成的sql:
Item.newest_items(Venue.pluck(:id)).to_sql
=> "SELECT max(items.id) as id, venue_id FROM \"items\"
INNER JOIN \"venues\" ON \"venues\".\"id\" = \"items\".\"venue_id\"
WHERE (venues.id IN (1,2,3))
GROUP BY \"items\".\"venue_id\""
所以每个场地都有最新的项目。但结果是,我想按照创建日期对结果进行排序。
如果我有订购条款:
class Item < ActiveRecord::Base
scope :newest_items, -> (venue_ids) {
select('max(items.id) as id, venue_id')
.joins(:venue).where('venues.id IN (?)', venue_ids)
.group(:venue_id).order('items.created_at desc')
}
end
sql:
Item.close_by_items(Venue.pluck(:id)).to_sql
=> "SELECT max(items.id) as id, venue_id
FROM \"items\" INNER JOIN \"venues\" ON \"venues\".\"id\" = \"items\".\"venue_id\"
WHERE (venues.id IN (1,2,3))
GROUP BY \"items\".\"venue_id\"
ORDER BY items.created_at desc"
我收到错误:
ActiveRecord :: StatementInvalid:PG :: GroupingError:ERROR:column&#34; items.created_at&#34;必须出现在GROUP BY子句中或用于聚合函数
为什么created_at必须出现在GROUP BY子句中或者在聚合函数中使用?我想要做的就是使用created_at time命令group by子句的结果。
答案 0 :(得分:0)
如果您只希望每个地点使用一个项目,则可以使用DISTINCT ON
代替分组。
class Item < ActiveRecord::Base
def self.newest_items(*venues)
select('DISTINCT ON(items.venue_id), items.*')
.where(venue_id: *venues)
.order('items.created_at DESC')
end
end
答案 1 :(得分:0)
实现此目的的另一种方法是将ORDER
置于子查询中,类似这样的东西应该按预期工作:
Item.close_by_items(Venue.pluck(:id)).to_sql
=> "SELECT max(sub.id) as id, sub.venue_id FROM (SELECT items.id, venue_id
FROM \"items\" INNER JOIN \"venues\" ON \"venues\".\"id\" = \"items\".\"venue_id\"
WHERE (venues.id IN (1,2,3)) ORDER BY items.created_at desc") AS sub
GROUP BY \"sub\".\"venue_id\"