【问题标题】:TSQL: Relational Division with Remainder (RDWR)SQL:带余数的关系除法 (RDWR)
【发布时间】:2021-12-21 13:51:52
【问题描述】:

我有一个映射表CandidatesSkills,它保存了候选人和他们所拥有的技能之间的映射。然后我有另一个表 JobRequirements 映射工作和该工作所需的技能。
如果候选人具备该工作所需的所有技能,他就可以申请该工作。候选人可以拥有额外的技能。给定CandiateID,我想找到候选人可以申请的所有工作。

我认为这是 SQL 中带余数的关系除法。还有一个article here 解释了确切的问题。 (注意:本文试图找到所有具有给定工作的所有技能的候选人。我的问题正好相反。我试图找到与给定候选人的技能相匹配的所有工作)

应聘者的技能

工作与所需技能的映射

根据数据集,下面的查询应该返回 JobID 2,3 和 5

这是我的 SQL(基于 Peter Larsson (PESO) 的 RDNR/RDWR 解决方案)

DECLARE @CandidateID INT = 1

SELECT JobID 
FROM        
(
    SELECT jr.JobID
        ,cnt=SUM(CASE WHEN jr.SkillID = c.SkillID THEN 1 ELSE 0 END)
        ,Items=COUNT(*)
    FROM dbo.JobRequirements AS jr
    CROSS JOIN dbo.CandidatesSkills  AS c    
    WHERE c.CandidateID = @CandidateID
    GROUP BY jr.JobID, jr.SkillID
) d
GROUP BY JobID
HAVING  SUM(cnt) = MIN(Items)
    AND MIN(cnt) >= 0;    

但是,查询不返回任何内容。试图找出我的查询出了什么问题

这里是SQL Fiddle

【问题讨论】:

标签: sql-server tsql sql-server-2012 sql-server-2016 relational-division


【解决方案1】:

类似:

DECLARE @CandidateID INT = 1;

with cj as
(
  select cs.CandidateId, 
         jr.JobId, 
         count(*) over (partition by jr.JobId, cs.CandidateId) skillsPosessed,
         (select count(*) from JobRequirements where JobId = jr.JobId) skillsRequired
  from CandidatesSkills cs
  join JobRequirements jr
    on cs.SkillId = jr.SkillId
)
select distinct cj.CandidateId, cj.JobId
from cj
where cj.skillsPosessed = cj.skillsRequired

【讨论】:

    【解决方案2】:

    在这种情况下,您使用多个除数进行关系除法。换句话说,您将 每个集合 JobRequirements 每个 JobID 除以该候选人的CandidateSkills

    在这种情况下,LEFT JOIN 解决方案要简单得多

    DECLARE @CandidateID INT = 1;
    
    SELECT jr.JobID
        ,Skills = COUNT(c.SkillID)
        ,Requirements = COUNT(*)
    FROM dbo.JobRequirements AS jr
    LEFT JOIN dbo.CandidatesSkills  AS c ON c.SkillID = jr.SkillID
        AND c.CandidateID = @CandidateID
    GROUP BY jr.JobID
    HAVING COUNT(*) = COUNT(c.SkillID);
    

    这样做的目的是将候选人的技能与要求保持一致。然后我们简单地将所有Requirements 计数为JobID,并确保它等于匹配数。

    另一种写法是

    HAVING COUNT(CASE WHEN c.SkillID IS NULL THEN 1 END) = 0;
    

    换句话说:不匹配的次数应该为零。

    SQL Fiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-26
      相关资源
      最近更新 更多