Sql 复杂ARel查询

Sql 复杂ARel查询,sql,ruby,activerecord,Sql,Ruby,Activerecord,我有一个复杂的查询,我无法使用sql或ActiveRecord来处理它。以下是我的模型: class Contact has_many :profile_answers end class ProfileAnswer belongs_to :contact belongs_to :profile_question end class ProfileQuestion has_many :profile_answers end 我正在尝试查找两个联系人的ProfileAnswe

我有一个复杂的查询,我无法使用sql或ActiveRecord来处理它。以下是我的模型:

class Contact
  has_many :profile_answers
end

class ProfileAnswer
  belongs_to :contact
  belongs_to :profile_question
end

class ProfileQuestion
  has_many :profile_answers
end
我正在尝试查找两个联系人的ProfileAnswers的数量,这两个联系人对于特定的ProfileAnswers问题具有相同的值。换言之:

获取两个联系人以相同值回答的特定个人资料问题的个人资料回答总数

我不想进行多个查询和筛选,因为我知道这只适用于Sql,我只是不知道如何做

我曾经考虑过在profile\u question\u id上自动加入profile\u答案,然后按相等的值进行过滤,但我仍然无法对此进行思考。非常感谢您的帮助。

我想这可以:

SELECT COUNT(DISTINCT profile_question_id)
FROM 
  ( SELECT profile_question_id
    FROM ProfileAnswer an
      JOIN ProfileQuestion qu
        ON qu.id = an.profile_question_id
    WHERE contact_id IN ( id1, id2 )
    GROUP BY profile_question_id
           , value
    HAVING COUNT(*) = 2
  ) AS grp
而且连接似乎没有被使用。因此,如果ProfileAnswer.profile_question_id不为空,这就足够了:

SELECT COUNT(*)
FROM 
  ( SELECT profile_question_id
    FROM ProfileAnswer
    WHERE contact_id IN ( id1, id2 )
    GROUP BY profile_question_id
           , value
    HAVING COUNT(*) = 2
  ) AS grp
为ID为id1和id2的两个特定联系人编辑

添加WHERE并将COUNT DINSTINCT更改为COUNT*

也许这个带有JOIN的版本可以更容易地适应ActiveRecord

使用连接

我认为这样做可以:

SELECT COUNT(DISTINCT profile_question_id)
FROM 
  ( SELECT profile_question_id
    FROM ProfileAnswer an
      JOIN ProfileQuestion qu
        ON qu.id = an.profile_question_id
    WHERE contact_id IN ( id1, id2 )
    GROUP BY profile_question_id
           , value
    HAVING COUNT(*) = 2
  ) AS grp
而且连接似乎没有被使用。因此,如果ProfileAnswer.profile_question_id不为空,这就足够了:

SELECT COUNT(*)
FROM 
  ( SELECT profile_question_id
    FROM ProfileAnswer
    WHERE contact_id IN ( id1, id2 )
    GROUP BY profile_question_id
           , value
    HAVING COUNT(*) = 2
  ) AS grp
为ID为id1和id2的两个特定联系人编辑

添加WHERE并将COUNT DINSTINCT更改为COUNT*

也许这个带有JOIN的版本可以更容易地适应ActiveRecord

使用连接


下面是我最后如何做到的,再次感谢@ypercube:

class ProfileAnswer < ActiveRecord::Base

  def self.for_contacts(*contacts)
   where :contact_id => contacts.collect(&:id)
  end

  def self.common_for_contacts(*contacts)
    select(:profile_question_id).for_contacts(*contacts).group(:profile_question_id, :value).having("count(*) = #{contacts.length}")
  end

  def self.common_count_for_contacts(*contacts)
    find_by_sql("select count(*) as answer_count from (#{common_for_contacts(*contacts).to_sql})").first.answer_count
  end
end

# Usage
ProfileAnswer.common_count_for_contacts(contact1, contact2[, contact3...])
最后仍然必须使用find_by_sql进行嵌套选择。。。不知道有没有办法解决这个问题


同样令人恼火的是,find_by_sql返回一个数组,所以我不得不使用。首先,它会给我一个对象,该对象上有我的answer_count属性。

下面是我如何完成的,再次感谢@ypercube:

class ProfileAnswer < ActiveRecord::Base

  def self.for_contacts(*contacts)
   where :contact_id => contacts.collect(&:id)
  end

  def self.common_for_contacts(*contacts)
    select(:profile_question_id).for_contacts(*contacts).group(:profile_question_id, :value).having("count(*) = #{contacts.length}")
  end

  def self.common_count_for_contacts(*contacts)
    find_by_sql("select count(*) as answer_count from (#{common_for_contacts(*contacts).to_sql})").first.answer_count
  end
end

# Usage
ProfileAnswer.common_count_for_contacts(contact1, contact2[, contact3...])
最后仍然必须使用find_by_sql进行嵌套选择。。。不知道有没有办法解决这个问题


同样令人恼火的是,find_by_sql返回一个数组,所以我不得不使用。首先,它会给我一个对象,该对象上有我的answer_count属性。

你是指两个特定联系人还是任意两个联系人?你是指两个特定联系人还是任意两个联系人?太棒了,我想这是可行的!只是想把它翻译成ARel,让它看起来更好看。只有一个问题。我假设having count*=x是这样的,x应该与我检查的联系人的数量相同?这样我就可以把这个通用于x个联系人了?@brad:没错。如果你想从x个人那里找到相同的答案,只需将2改为x,并将x ID放入in。。。列表。@brad:我已经添加了一个带有JoinAweam的版本,我认为这很有效!只是想把它翻译成ARel,让它看起来更好看。只有一个问题。我假设having count*=x是这样的,x应该与我检查的联系人的数量相同?这样我就可以把这个通用于x个联系人了?@brad:没错。如果你想从x个人那里找到相同的答案,只需将2改为x,并将x ID放入in。。。列表。@brad:我添加了一个带有JOIN的版本