我有一个复杂的查询,我无法解决(使用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
我正在尝试查找针对特定ProfileQuestion具有相同value
的两个联系人的ProfileAnswers数。换句话说:
获取两个联系人使用相同值的特定profile_question回答的个人资料答案总数
我不想进行多次查询和过滤,因为我知道这只能用Sql实现,我只是不知道该怎么做
我曾考虑在profile_answers
上profile_question_id
进行自我加入,然后按value
过滤相等,但我仍无法解决这个问题。非常感谢任何帮助。
答案 0 :(得分:1)
我认为这样做:
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
似乎没有使用JOIN
。因此,如果ProfileAnswer.profile_question_id
为NOT NULL
,这就足够了:
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。
使用JOIN
SELECT COUNT(*)
FROM ProfileAnswer a
JOIN ProfileAnswer b
ON a.profile_question_id = b.profile_question_id
AND a.value = b.value
WHERE a.contact_id = id1
AND b.contact_id = id2
答案 1 :(得分:0)
以下是我最终如何做到这一点,再次感谢@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返回一个数组,所以我不得不使用.first
然后给我一个具有answer_count
属性的对象。