复杂的SQL语句:选择匹配多个表

use*_*881 6 sql

我有桌子:

  • Candidates
  • CandidateLanguages
  • CandidateSkills

每位候选人可能拥有1种以上的语言和1种以上的技能

所以对于Candidate"FRED",他的记录CandidateLanguages可能是

FRED - ENGLISH
FRED - FRENCH
Run Code Online (Sandbox Code Playgroud)

他的记录CandidateSkills可能是

FRED - RUNNING
FRED - JUMPING
Run Code Online (Sandbox Code Playgroud)

而对于Candidate"JIM"他的记录CandidateLanguages可能是

JIM - ENGLISH
Run Code Online (Sandbox Code Playgroud)

他的记录CandidateSkills可能是

JIM - RUNNING
Run Code Online (Sandbox Code Playgroud)

我的查询需要选择符合多种技能和语言的候选人.

例如,用英语:

选择所有所选语言的所有候选人,并拥有所有选定的技能......

或换一种方式....

SELECT ALL candidates WHERE 
(language = 'FRENCH' AND language is 'ENGLISH') AND 
(skill = 'RUNNING' AND skill = 'JUMPING') 
Run Code Online (Sandbox Code Playgroud)

在上面两个候选人中,这应该只返回"FRED"

我知道问题是尝试从语言和技能表中选择多个记录,我认为可能需要连接,但现在我迷路了......

ype*_*eᵀᴹ 4

您正在解决的问题称为关系划分

请参阅这篇文章:Divided We Stand: The SQL of Relational Division和这个问题,了解解决它的几种方法:How to filter SQL results in a has-many-through relation

解决这个问题的一种方法(通常来说,这是最有效的):

SELECT ALL c.candidate
FROM Candidates c
  JOIN CandidateLanguages lang1
    ON  lang1.candidate = c.candidate 
    AND lang1.language = 'English'
  JOIN CandidateLanguages lang2
    ON  lang2.candidate = c.candidate 
    AND lang2.language = 'French'
  JOIN CandidateSkills sk1
    ON  sk1.candidate = candidate 
    AND sk1.skill = 'Running'
  JOIN CandidateSkills sk2
    ON  sk2.candidate = candidate 
    AND sk2.skill = 'Jumping' ;
Run Code Online (Sandbox Code Playgroud)

另一种方法似乎更容易编写,特别是在涉及很多语言和技能的情况下,是使用两个派生表,GROUP BY每个表中包含:

SELECT ALL c.candidate
FROM Candidates c
  JOIN 
    ( SELECT candidate
      FROM CandidateLanguages
      WHERE language IN ('English', 'French')
      GROUP BY candidate
      HAVING COUNT(*) = 2                     -- the number of languages
    ) AS lang
      ON  lang.candidate = c.candidate 
  JOIN 
    ( SELECT candidate
      FROM CandidateSkills 
      WHERE skill IN ('Running', 'Jumping')
      GROUP BY candidate
      HAVING COUNT(*) = 2                     -- the number of skills
    ) AS sk
      ON  sk.candidate = c.candidate ;
Run Code Online (Sandbox Code Playgroud)

  • 如果您拥有 15 种语言和 60 种技能怎么办? (3认同)