Запрос на сопоставление значений, разделенных запятыми, из двух таблиц - PullRequest
0 голосов
/ 01 апреля 2011

У меня есть две таблицы. Студент и работа. Мне нужно искать студентов, которые обладают всеми навыками, необходимыми для работы.

    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

Ответы [ 5 ]

0 голосов
/ 01 апреля 2011
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 равно SPLIT в SQL Server. Я также рекомендую еще больше нормализовать ваш стол. Использование одной строки на пару id-> skill поможет вам избавиться от операции SPLIT.

0 голосов
/ 01 апреля 2011

Я бы порекомендовал изменить вашу схему, чтобы не сохранять список навыков в качестве значения 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
    )

Это довольно быстрая попытка, поэтому могут быть другие способы структурировать этот запрос - с этим стоит поиграть, если вы сможете внести изменения в схему.

0 голосов
/ 01 апреля 2011

Вы можете попробовать это .. но я догадываюсь .. Я не знаю, даже если возможно сделать что-то вроде этого:

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
0 голосов
/ 01 апреля 2011
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)
0 голосов
/ 01 апреля 2011

попробуйте это (я не проверял):

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...