Rails:通过相关记录的组合查找记录

时间:2014-03-09 01:27:13

标签: ruby-on-rails activerecord

在Ruby on Rails 4应用程序中,请考虑以下数据模型:

Question:
  id: int
  # [...]
  has_many: Answers

Answer:
  id: int
  question_id: int
  # [...]
  belongs_to: Question
  has_many: Results through AnswerResult

AnswerResult:
  id: int
  answer_id: int
  result_id: int

Result:
  id: int
  # [...]
  has_many: Answers through AnswerResult

使用此模型,请考虑以下行为:

  1. 有多个问题,都有多个答案。
  2. 每个特定的答案组合都会产生一个且只有一个结果。
  3. 现在,我的问题是:

    在用户回答了我的所有问题之后,我最终得到了带有用户答案ID的问题ID哈希值。我想找到属于这种答案组合的结果。

    我该怎么做?


    编辑:示例:(根据评论中的要求)

    问题和答案及其ID

    Gender:     [Question #1]
      - Male    [Answer   #1]
      - Female  [Answer   #2]
    Age:        [Question #2]
      - < 30    [Answer   #3]
      - 30 - 65 [Answer   #4]
      - > 65    [Answer   #5]
    

    结果:

    Junior man   [#1]  bound to answers [#1, #3]
    Senior man   [#2]  bound to answers [#1, #4]
    Old man      [#3]  bound to answers [#1, #5]
    Junior woman [#4]  bound to answers [#2, #3]
    Senior woman [#5]  bound to answers [#2, #4]
    Old woman    [#6]  bound to answers [#2, #5]
    

    输入:

    { 
      1 => 2, # Gender: female
      2 => 4  # Age:    30-65
    }
    

    函数查找绑定到答案#2和#4

    的结果

    输出:Result #5: Senior woman

2 个答案:

答案 0 :(得分:1)

input = { 
  1 => 2, # Gender: female
  2 => 4  # Age:    30-65
}

answers = input.inject([]){|ary, input| ary << input[1] } # [2,4]

results = {
  "Junior man"   => [1,3],
  "Senior man"   => [1,4],
  "Old man"      => [1,5],
  "Junior woman" => [2,3],
  "Senior woman" => [2,4],
  "Old woman"    => [2,5]
}

output = results.select {|k,v| v == answers} # "Senior woman" => [2,4]

output.keys[0] # "Senior Woman"

答案 1 :(得分:1)

除非您了解 Relational Division in SQL 这个概念,否则这是在SQL中要解决的难题。

以下查询为您提供预期结果

SELECT results.*
  FROM results
  INNER JOIN answer_results 
    ON results.id = answer_results.result_id
  WHERE answer_results.answer_id IN (2, 4)
  GROUP BY results.id
  HAVING COUNT(results.id) = 2

<强> SQL Fiddle

在ActiveRecord

中,您可能未经过测试(可能会更改某些内容)可能的解决方案
answer_ids = input.map(&:last)

Result.joins(:answer_results).where("answer_results.answer_id IN (?)",
 answer_ids).group('results.id').having('COUNT(results.id) = ?', answer_ids.size)