我有以下型号:
# contributor.rb
class Contributor < ApplicationRecord
has_many :skill_groupings
has_many :skills, through: :skill_groupings
end
# skill_grouping.rb
class SkillGrouping < ApplicationRecord
belongs_to :skill
belongs_to :contributor
end
# skill.rb
class Skill < ApplicationRecord
has_many :skill_groupings
has_many :contributors, through: :skill_groupings
end
我想搜索(SQL查询)其skill_ids包含所有包含在数组中的值的贡献者。
假设数据如下:
contributor_1.skill_ids: [2, 3, 6, 7]
contributor_2.skill_ids: [4, 7]
contributor_3.skill_ids: [9]
contributor_4.skill_ids: []
wanted_ids = [3, 7]
Contributor.joins(:skill_groupings).where(skill_groupings: { skill_id: wanted_ids }).distinct
返回技能ID为3 或 7的贡献者,因此为[contributor_1, contributor_2]
。这不是我想要的。
查询的结果应为[contributor_1]
,因为只有contributor_1
具有wanted_ids
中所有 的技能ID。
不幸的是,skill_ids
似乎只是Rails引入的属性,在SQL中不可用。
如何仅通过SQL查询来实现这一目标?
答案 0 :(得分:0)
假设一个贡献者不能一次拥有相同的技能,我能看到的最简单的方法是找到所有具有与这些技能相同数量的技能的贡献者,例如
Contributor.joins(:skills)
.where(skills: { id: wanted_ids })
.group(:id)
.having("COUNT(skills.id) = #{wanted_ids.uniq.size}"))
这将导致给定wanted_ids = [3, 7]
的以下SQL
SELECT
contributors.*
FROM
contributors
INNER JOIN skill_groupings ON skill_groupings.contributor_id = contributors.id
INNER JOIN skills ON skills.id = skill_groupings.skill_id
WHERE
skills.id IN (3,7)
GROUP BY
contributors.id
HAVING
COUNT(skills.id) = 2
这仅适用于PostgreSQL,因为此SQL Server允许按主键进行分组,同时仍选择整个列。对于其他数据库,您将需要一个子查询,例如:
Contributor.where(id:
Contributor.joins(:skills)
.select(:id)
.where(skills: { id: wanted_ids })
.group(:id)
.having("COUNT(skills.id) = #{wanted_ids.uniq.size}")
)