Rails:通过连接表获取关联计数

时间:2018-09-08 18:55:32

标签: ruby-on-rails ruby postgresql activerecord ruby-on-rails-5

我有一个名为“ 事实”的实体,该实体与另一个名为“ User ”的实体有关系,这种关系称为“ 反馈”,该字段具有3个字段, [user_id,fact_id,分数] ,每当有人提供反馈时,他都会得到对事实做出的反馈( user_id )(< strong> fact_id )和符合条件的内容( 0,1,2 )。 好吧,现在我想获取包含其资格的事实清单,例如:

fact : {id: 3, name: "some name", number_of_zero: 7, number_of_one: 3, number_of_two: 3}

其中number_of是合格的次数。

数据库架构:

  create_table "facts", force: :cascade do |t|
    t.string "title"
    t.string "description"
    t.integer "user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.string "last_name"
  end

create_table "feedbacks", force: :cascade do |t|
    t.integer "score"
    t.integer "user_id"
    t.integer "fact_id"
    t.index ["fact_id"], name: "index_feedbacks_on_fact_id"
    t.index ["user_id"], name: "index_feedbacks_on_user_id"
  end

关系:

class Feedback < ApplicationRecord
  belongs_to :user
  belongs_to :fact
end

3 个答案:

答案 0 :(得分:1)

Fact.
  group(:id, :name).
  select(:id, name).
  left_joins(:feedbacks).
  select("COUNT(feedbacks.id) FILTER (WHERE score = 0) AS number_of_zero").
  select("COUNT(feedbacks.id) FILTER (WHERE score = 1) AS number_of_one").
  select("COUNT(feedbacks.id) FILTER (WHERE score = 2) AS number_of_two")

您需要left_joins,以便还返回反馈为0的事实(每个计数列为0)。

如罗汉所言,您需要在has_many :feedbacks中添加fact.rb

有更复杂的解决方案可以适应任何数量的可能得分,但在这种情况下,可能会显得过于热情。

编辑:对于SQLite (我认为它支持相关的子查询...)

Fact.
  select(:id, name).
  select("(SELECT COUNT(*) FROM feedbacks WHERE score = 0 AND fact_id = facts.id) AS number_of_zero").
  select("(SELECT COUNT(*) FROM feedbacks WHERE score = 1 AND fact_id = facts.id) AS number_of_one").
  select("(SELECT COUNT(*) FROM feedbacks WHERE score = 2 AND fact_id = facts.id) AS number_of_two")

答案 1 :(得分:0)

根据帖子中提供的描述,您似乎想要事实的详细信息以及每个uniq事实的得分。

下面提到的某些方法可以帮助您实现:

Fact.joins(:feedbacks).select("facts.id, facts.title,CASE when feedbacks.score is 0 
then count(feedbacks.score) as score_0 end,
CASE when feedbacks.score is 1 then count(feedbacks.score) as score_1 end,
CASE when feedbacks.score is 2 then count(feedbacks.score) as score_2 end")
.group("feedbacks.score")

上述查询将反馈与事实结合在一起,然后对得分值进行分组,因为只有三个值,即0,1,2(如文章中所述)。

答案 2 :(得分:0)

Model:
class Feedback < ApplicationRecord
  belongs_to :user
  belongs_to :fact
end
class Fact < ApplicationRecord
 has_many :feedbacks
end
 fact = Fact.all
  array = []
 fact.each do |each_fact|
    arr = {}
    each_fact.feedbacks do |each_feedback|
       arr["id"] = each_feed_back.id
       arr["name"] = each_feedback.name
       arr["no_of_zero"] = each_feedback.score 
       array << arr
   end
end