Rails / SQL:查找有关belongs_to关系的统计信息

时间:2016-06-30 12:51:08

标签: sql ruby-on-rails postgresql activerecord logic

我有以下型号

class Project
  has_many :contributions
end

class Contributor
  has_many :contributions
end

class Contribution
  belongs_to :contributor
  belongs_to :project
end

我试图找出有多少贡献者贡献了多少项目,并按项目数量排序。

示例:

- Person 1 made contribution to Project 1
- Person 1 made contribution to Project 2
- Person 2 made contribution to Project 1
- Person 2 made contribution to Project 3
- Person 2 made contribution to Project 4
- Person 3 made contribution to Project 4
- Person 3 made contribution to Project 5

在这种情况下

- Person 1 made 2 contributions in 2 seperate projects.
- Person 2 made 3 contributions in 3 seperate projects.
- Person 3 made 2 contributions in 2 seperate projects.

表示

- 2 people made 2 contributions
- 1 person made 3 contributions

结果是:{ 2 => 2, 1 => 3 }

这是我做的:

Contributor.joins(:contributions).order("count(contributions.id) asc").group("contributor.id").count

这给了我每个贡献者的贡献,但不是我所寻找的。

2 个答案:

答案 0 :(得分:1)

试试这个:

Contributor.joins(:contributions).order("count(contributions.id) asc").group("contributor.id").count.group_by{|i| i.last}.map{|a| [a.last.count,a.first]}

答案 1 :(得分:1)

# First, you need to count the distinct contributions for every contributor

contributors_info = Contributor.joins(:contributions).group("contributors.id").count("DISTINCT contributions.id")

   (0.4ms)  SELECT COUNT(DISTINCT contributions.id) AS count_distinct_contributions_id, contributors.id AS contributors_id FROM "contributors" INNER JOIN "contributions" ON "contributions"."contributor_id" = "contributors"."id" GROUP BY contributors.id

=> {1=>2, 2=>3, 3=>2}

您希望结果如下:

  
      
  • 2人做出了2次贡献
  •   
  • 1人做出了3次贡献
  •   
  • 结果是:{2 => 2,1 => 3}
  •   

但如果有另一个人做了4次贡献,那么你的结果将是:{ 2 => 2, 1 => 3, 1 => 4 },这不是有效的哈希。这意味着您必须更改结果构造,我建议您使用contribution_count作为键,并将人数作为值,因为contribution_count将是唯一的。

# Then, use the previous information to get how many people made how many contributions

contributors_info.reduce({}) do |result, (_, contribution_count)|
  result[contribution_count] = (result[contribution_count] ||= 0) + 1
  result
end

# two contributions => 2 people, three contributions => 1 person
=> {2=>2, 3=>1}