【问题标题】:Rails: How to get all of the records that have the maximum count of a relation with a where clauseRails:如何使用where子句获取具有最大关系计数的所有记录
【发布时间】:2017-12-31 07:33:17
【问题描述】:

Rails 5.1.2

这是有问题的两个模型。

class Person < ApplicationRecord
  has_many :awards
end

class Award < Application Record
  belongs_to :person
end

Award 模型有一个名为rank 的列,可以是123,还有一个名为category 的列(也是整数,但现在我们只使用字母) .

我正在尝试根据他们的awards 的某个排名对People 进行排名。许多人可以拥有相同数量的等级。例如,40 人可能有 30 个类别 X 的 1 级奖项。

例如:

A 类别获奖最多

People 授予AwardRank 1 8 次

  • 第 1 个人
  • 第二个人

People 授予 AwardRank 2 30 次

  • 第 1 个人
  • 第 7 人
  • 19 号人

People 授予AwardRank 3 60 次

  • 第二个人
  • 19 号人
  • 44 人

我想构建一个返回 People 集合的查询。

从逻辑上讲,这就是我的查询应该做的(在伪代码中):

Get all `people` who have the maximum `count` of awards where `awards.category` is `A` and `awards.rank` is `1`.

...对排名2 和排名3 重复此操作。

由于类别的含义,counter_cache 不起作用(除非我为每个类别创建一个 counter_cache,但这感觉非常多余且不灵活)。

像往常一样,一个听起来很简单的想法结果比我想象的要复杂得多,我不知道如何实现它。

【问题讨论】:

  • 它更像是count 的降序获得所有people,其中awards.categoryAawards.rank1
  • 顺序无关紧要,因为我希望所有people 拥有某个类别和排名的某个奖项的最大count。我可以这样做:Award.where(rank: 1, category: 0).group(:person_id).count 它将返回一个有序的哈希 { id(integer) =&gt; count(integer) },然后按值排序,并获取所有计数最高的 id(哈希的键)(可以有多人排名第一)。
  • 但是,我上面评论的解决方案绝对不优雅,而且可能会很慢,特别是如果我在一页上使用各种类别和排名组合来执行此操作。

标签: ruby-on-rails database querying


【解决方案1】:
awards_having_max_count_of_persons_for_each_category_and_rank = Award.group(:category, :rank).order('count(awards.person_id)')

# you can do something like this if you'd like to key-value pairs:
hash = {}
awards_having_max_count_of_persons_for_each_category_and_rank.each do |award|
  hash[{category: award.category, rank: award.rank}] = award.person_id
end

puts hash
# => {
#      {category: 1, rank: 1} => 1,
#      {category: 1, rank: 2} => 3,
#      {category: 1, rank: 3} => 2,
#      {category: 2, rank: 1} => 9,
#      ...
#    }
# where 1, 3, 2, and 9 are person_ids

【讨论】:

  • 拥有COUNT(awards.id) 将始终返回 1 作为计数...我猜你的意思是 COUNT(awardes.user_id)
  • 哦,你是对的! :) 虽然我认为我需要修改我的答案,因为 OP 刚刚回复了我上面的评论,看起来这不是他/她想要的。
  • 哦等等。不,实际上应该是awards.id,因为我正在对相关奖励记录的计数进行排序。
  • 虽然,这是在我认为我理解 OP 之前,但我仍然需要更新我的答案,以反映你所描述的内容。
  • 无论如何我都试过了,但我得到了这个错误信息:ActiveRecord::StatementInvalid: SQLite3::SQLException: misuse of aggregate: COUNT(): SELECT "people".* FROM "people" LEFT OUTER JOIN "awards" ON "awards"."person_id" = "people"."id" WHERE "awards"."category" = ? AND "awards"."rank" = ? ORDER BY COUNT(awards.person_id) DESC LIMIT ?
猜你喜欢
  • 1970-01-01
  • 2015-10-14
  • 2023-04-01
  • 2016-03-25
  • 2019-06-12
  • 1970-01-01
  • 2015-03-07
  • 2015-05-18
  • 2018-09-26
相关资源
最近更新 更多