我有两张桌子。学生和工作。 我需要搜索具备工作所需技能的学生。
Student Job
StudentId MandSkills JobPostId MandSkills
208 2,16,17 36 2,16,18
209 2,16
210 2,18,34
211 2,16,17
212 2,17,16,23
213 2,16,17
214 2,16,17
215 2,18,17,28
217 2,16,17
我写了一个查询
SELECT
S.StudentId, S.MandSkills, JP.items
FROM
Split((SELECT MandSkills FROM JobPosts WHERE JobPostId = 36),',') JP,
Students S
WHERE
JP.items IN (SELECT items FROM Split(S.MandSkills,','))
[Split()将逗号分隔的字符串值作为输入,并以表格形式返回单独的值]
返回如下结果:
studentId MandSkills items
208 2,16,17 2
209 2,16 2
210 2 2
211 2,16,17 2
212 2,16,17 2
213 2,16,17 2
214 2,16,17 2
215 2,16,17 2
217 2,16,17 2
218 2,16,17,26 2
219 2,16 2
221 2,16 2
208 2,16,17 16
209 2,16 16
211 2,16,17 16
212 2,16,17 16
213 2,16,17 16
214 2,16,17 16
215 2,16,17 16
217 2,16,17 16
218 2,16,17,26 16
219 2,16 16
220 16,17 16
221 2,16 16
它仅检查一项技能。
我想选择具备三种技能的学生。
请帮帮我。
提前致谢。
-Aarti
答案 0 :(得分:0)
尝试这个(我还没有测试过):
SELECT S.StudentId, S.MandSkills, JP.items
FROM Students S
, Split((select MandSkills from JobPosts where JobPostId=36),',') JP
WHERE NOT EXISTS
(SELECT NULL
FROM (SELECT JP1.items JP_items, S1.items S_items
FROM Split((select MandSkills
from JobPosts
where JobPostId=36),',') JP1
LEFT JOIN Split(S.MandSkills,',') S1
ON JP1.items = S1.items) A
WHERE S_items IS NULL)
答案 1 :(得分:0)
你可以尝试这个..但我猜...我不知道即使有可能做这样的事情:
select *
from Student s
join Job j on (select count(*)-sum(case when jms.items is not null then 1 else 0 end)
from split(j.MandSkills,',') sms
left join split(s.MandSkills,',') jms on sms.items=jms.items)=0
答案 2 :(得分:0)
Select S.StudentId, JP.MandSkills
from JobPosts JP
cross apply Split(JP.MandSkills, ',') JPS
inner join (
select S.StudentId, S.MandSkills, SS.items
from Students S
cross apply Split(S.MandSkills, ',') SS) S on S.items = JPS.items
where JP.JobPostId=36
group by S.StudentId, JP.MandSkills
having LEN(JP.MandSkills)-LEN(replace(JP.MandSkills,',',''))+1 = COUNT(distinct S.items)
答案 3 :(得分:0)
我建议您更改架构,不要将技能列表存储为每个表中的CSV值。当您最终必须将值拆分并且不使用索引时,性能将受到影响。
相反,我会创建2个额外的表:
StudentSkill
-------------
StudentId
SkillId
JobSkill
--------
JobPostId
SkillId
在每种情况下,两个字段构成主键并引用每列的相应主表(即StudentId - > Student.StudentId)
现在你有一个架构可以导致SARGable(可以使用索引)的查询。
那么一个适合你的查询是:
;WITH CTEJobSkills AS
(
SELECT SkillID
FROM JobSkill
WHERE JobPostID = 1
)
SELECT s.StudentID
FROM Student s
WHERE NOT EXISTS
(
SELECT *
FROM CTEJobSkills js
LEFT JOIN StudentSkill ss ON js.SkillID = ss.SkillID AND ss.StudentID = s.StudentID
WHERE ss.SkillID IS NULL
)
这是一个相当快速的尝试,因此可能有其他方法来构建该查询 - 如果您可以更改架构值得玩弄。
答案 4 :(得分:0)
SELECT sid FROM
(
Select sid, jid, ssk, jsk FROM
(SELECT id sid, regexp_split_to_table(stud.skill, ',') ssk FROM stud) s,
(SELECT id jid, regexp_split_to_table(job.skill, ',') jsk FROM job WHERE id = 36) j
WHERE ssk = jsk
ORDER BY sid, jsk, ssk
) jn
GROUP BY sid
HAVING count(*) = (SELECT count(*) FROM (SELECT id jid, regexp_split_to_table(job.skill, ',') jsk FROM job WHERE id = 36) sj)
抱歉,我使用POSTGRESQL进行快速检查。 regexp_split_to_table等于SQL Server中的SPLIT。 我也建议进一步规范你的表格结构。每个id->技能对使用一行可以让你摆脱SPLIT操作。