【问题标题】:Rails: get count of association through join tableRails:通过连接表获取关联计数
【发布时间】:2018-09-08 18:55:31
【问题描述】:

我有一个名为“Fact”的实体,该实体与另一个名为“User”的实体有关系,这种关系称为“Feedback >" 有 3 个字段 [user_id, fact_id, score] 每次一个人给出反馈时,他得到的反馈是谁做的(user_id)到什么事实(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

【问题讨论】:

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


    【解决方案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)。

    如Rohan所说,您需要在fact.rb中添加has_many :feedbacks

    有更复杂的解决方案可以适应任意数量的可能分数,但在这种情况下,这将是过分热心的。

    编辑:对于 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")
    

    【讨论】:

    • 你好,我添加了 has_many :feedbacks 但现在我明白了:SQLite3::SQLException: near "(": syntax error: SELECT "facts"."id", "facts"."title", COUNT(feedbacks.id) FILTER (WHERE score = 0) AS number_of_zero, COUNT(feedbacks.id) FILTER (WHERE score = 1) AS number_of_one, COUNT(feedbacks.id) FILTER (WHERE score = 2) AS number_of_two FROM "facts" LEFT OUTER JOIN "feedbacks" ON "feedbacks"."fact_id" = "facts"."id" GROUP BY "facts"."id", "facts"."title"
    • 该问题的标签为postgresql,因此针对该风味给出了答案。 sqlite 不支持FILTER。更新 sqlite 的查询...您也可以考虑使用 postgres,它更灵活 ;)
    • 还有一个问题,我有一张带回形针的图片,现在我已经很完美了,但是如果不是默认 url,图片没有得到真实的 url,你知道发生了什么
    【解决方案2】:
    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
    

    【讨论】:

      【解决方案3】:

      根据帖子中提供的描述,您似乎需要事实详细信息以及每个 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(如帖子中所述)。

      【讨论】:

      • 我明白了:**无法将“事实”加入名为“反馈”的关联;也许你拼错了? ** 我认为这是因为关系有 ** 反馈 ** 而不是事实,我不知道!
      • 因为一个事实可以有很多反馈,因此必须定义关系 has_many :feedbacks in fact.rb
      • 你是对的,但现在我明白了:SQLite3::SQLException: near "as": syntax error: 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 FROM "facts" INNER JOIN "feedbacks" ON "feedbacks"."fact_id" = "facts"."id" GROUP BY feedbacks.score
      猜你喜欢
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多