使用SQL左连接查询指定申请者未申请岗位返回全部岗位问题
问题根源
原查询返回全量岗位、不符合预期的核心原因如下:
- 左连接未做关联范围限定,直接将全量申请记录与岗位表做关联,后续
applicant != 28的判断逻辑会把所有存在非28号申请者投递记录的岗位全部筛出——哪怕该岗位已经被28号用户申请过,只要有其他用户投递过,就会被错误计入结果。 - 结合提供的样例数据:ID为2的web developer岗位,同时存在applicant=28、applicant=1的两条申请记录,原查询的where条件会匹配到applicant=1的这条记录(满足
applicant != 28),因此把这个28号用户已经投递过的岗位错误返回,最终导致所有岗位都被查询出来。
正确实现方案
- 方案1:将28号用户的申请匹配逻辑限定在左连接的关联条件中
左连接时仅关联applicant=28的申请记录,关联结果为空的岗位,就是28号用户从未投递的岗位。
注意:不能把SELECT j.id, j.title, j.description FROM `job` j LEFT JOIN `application` a ON j.id = a.job_id AND a.applicant = 28 -- 仅匹配28号用户的申请记录 WHERE a.id IS NULL -- 不存在28对应当前岗位的申请记录a.applicant = 28的判断放到where子句中,否则左连接会被退化为内连接,无申请记录的岗位会被直接过滤,丢失查询结果。 - 方案2:使用
NOT EXISTS实现,逻辑直观且无空值风险
逐岗位判断,不存在「28号用户投递当前岗位」的申请记录时,直接返回该岗位。匹配到任意一条符合条件的申请记录就会终止子查询判断,查询效率更高。SELECT j.id, j.title, j.description FROM `job` j WHERE NOT EXISTS ( SELECT 1 FROM `application` a WHERE a.job_id = j.id AND a.applicant = 28 ) - 方案3:使用
NOT IN实现,需注意空值陷阱
先提取所有28号用户投递过的岗位ID集合,再从岗位表中筛选不在该集合内的岗位。SELECT j.id, j.title, j.description FROM `job` j WHERE j.id NOT IN ( SELECT DISTINCT a.job_id FROM `application` a WHERE a.applicant = 28 AND a.job_id IS NOT NULL -- 必须过滤空值,避免查询返回空结果 )
内容的提问来源于stack exchange,提问作者jacakal
相关产品推荐
相关产品推荐

