我有一个名为“Fact”的实体,这个实体与另一个名为“User”的实体有关系,这种关系被称为“反馈”,每当一个人给出他得到的反馈时,它有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
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所说,你需要在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")
根据帖子中提供的描述,您似乎想要事实细节以及每个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(如帖子中所述)。
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