2013-11-10 4 views
5

Я боролся с этим в течение нескольких дней, так извинения, если я слишком запутанных вещи ...Найти «пропущенные» строки через два набор результатов

У меня есть ряд таблиц, которые определяют:

  1. Группы навыков
  2. навыки
  3. навыки в пределах вышеуказанных групп (многие-ко-многим)
  4. работа роли
  5. навыки, с теми работы роли (многие-ко-многим)

Структура базы данных выглядит следующим образом: Schema

Мне нужно создать результирующий набор, содержащий следующие данные:

Для всех из ролей работы, показать все навыки в рамках этой работы ролей. Однако также включают навыки в соответствующих группах, которые были не включены в каждую роль (обозначается NULL или любым способом другой).

Для создания таблиц и данных см. Этот рабочий код. SQL Fiddle
Извинения за длину, я сделал много вставок, чтобы создать реалистичный пример.

Обратите внимание, что умение PowerPoint не добавлено к роли HR Manager, но добавляются другие навыки из этой же группы. Также обратите внимание, что навык Recruitment Policy не добавлен в роль Software Manager, но мне не нужно видеть этот пробел, потому что в этой роли нет других навыков в этой группе.

Результаты, которые я бы направлены на походили бы это (за исключением Супер звезда роль для краткости):

RoleTitle    GroupTitle     SkillTitle    SkillIsInRole 
----------------------- -------------------------- -------------------------------------- 
Software Manager  Microsoft Office   Excel     1 
Software Manager  Microsoft Office   Word      1 
Software Manager  Microsoft Office   PowerPoint    1 
Software Manager  Microsoft SQL Server  Query Design    1 
Software Manager  Microsoft SQL Server  Stored Procedures  1 
Software Manager  Microsoft SQL Server  Failover Clustering  1 
HR Manager    Microsoft Office   Excel     1 
HR Manager    Microsoft Office   Word      1 
HR Manager    Microsoft Office   PowerPoint    NULL <-- not added to role but exists in same group as other used skills 
HR Manager    HR       Recruitment Policy  1 

ответ

3

Получение всех навыков для группы, связанной с ролью, несколько прост и обрабатывается в относительно самостоятельном пояснении roles cte ниже. Исходя из этого, единственный способ, которым я могу думать о том, связано ли навык «напрямую» с ролью, - это OUTER APPLY ING, результат, полученный в результате набора фактических навыков для роли.

;WITH skills AS 
(
    SELECT g.GroupId, g.GroupTitle, s.SkillId, s.SkillTitle 
    FROM @tbl_GroupsSkills gs 
    INNER JOIN @tbl_Groups g ON g.GroupId = gs.GroupId 
    INNER JOIN @tbl_Skills s ON s.SkillId = gs.SkillId 
) 
, roles AS 
(
    SELECT DISTINCT jr.Id RoleId, jr.RoleTitle, gs.GroupId 
    FROM @tbl_jobroles jr 
    INNER JOIN @tbl_rolesskills rs ON rs.RoleId = jr.ID 
    INNER JOIN @tbl_GroupsSkills gs ON gs.LinkId = rs.LinkId 
) 
SELECT 
    roles.RoleTitle, 
    skills.GroupTitle, 
    skills.SkillTitle, 
    t.SkillIsInRole 
FROM skills 
JOIN roles ON roles.GroupId = skills.GroupId 
OUTER APPLY 
(
    SELECT 1 SkillIsInRole 
    FROM @tbl_rolesskills rs 
    INNER JOIN @tbl_jobroles r ON rs.RoleID = r.ID 
    INNER JOIN @tbl_groupsskills gs ON gs.LinkID = rs.LinkID 
    INNER JOIN @tbl_groups g ON g.groupID = gs.GroupID 
    INNER JOIN @tbl_skills s ON s.skillID = gs.SkillID 
    WHERE s.SkillId = skills.SkillId 
    AND g.GroupId = skills.GroupId 
    AND r.Id = roles.RoleId 
) t 
ORDER BY roles.RoleTitle, skills.GroupTitle, skills.SkillTitle 

Изменить: OUTER APPLY может быть обработан с LEFT JOIN

LEFT JOIN (
    SELECT s.SkillId, g.GroupId, r.Id RoleId, 1 SkillIsInRole 
    FROM @tbl_rolesskills rs 
    INNER JOIN @tbl_jobroles r ON rs.RoleID = r.ID 
    INNER JOIN @tbl_groupsskills gs ON gs.LinkID = rs.LinkID 
    INNER JOIN @tbl_groups g ON g.groupID = gs.GroupID 
    INNER JOIN @tbl_skills s ON s.skillID = gs.SkillID 
) t ON t.SkillId = skills.SkillId 
    AND t.GroupId = skills.GroupId 
    AND t.RoleId = roles.RoleId 

demo

+0

Спасибо огромное. Я попробую утром, когда вернусь на работу. – EvilDr

+0

Потрясающий. Огромное спасибо. Я буду смотреть на ваш веб-сайт «tba», и когда вы ищете новую работу, я буду проверять, позволяют ли наши финансы :-) – EvilDr

+0

Просто скажите, пожалуйста. Ваш запрос выполняет фракцию быстрее, чем у Богдана, но имеет гораздо больше кода. У вас есть информация о том, почему это может быть? Из-за этого я выбрал ваш ответ как правильный. – EvilDr

1

Я думаю, вы должны подготовить набор всех возможных комбинаций ролей с одной стороны, и группы навыков от другой. Это делается путем умножения Декарта (обычно выполняется CROSS JOIN). В результате у вас будет список каждой роли в сочетании со списком всех возможных комбинаций групповых навыков. После этого вы можете ВСПОМОГАТЬ СОЕДИНЕНИЕ этого результата с помощью таблицы tbl_RolesSkills. Это даст вам то, что вам нужно. Вы можете сделать это, используя CTE или дополнительный запрос.

Придется выглядит как this example

На самом деле CROSS JOIN не нужен, я пропустил часть с «конкретными ролями есть только конкретные наборы групп». Только один подзапрос может быть выполнен также с помощью CTE (Common table expression).

Я также исключаю роль «Супер звезды». Если вы хотите добавить его, просто удалите раздел WHERE.

+0

Спасибо. Не могли бы вы разместить пример в скрипте SQL Fiddle? – EvilDr

+0

Извините, я пишу ответ от iPad, и мне тяжело писать сценарии :) –

+0

Отлично. Большое спасибо. Очень ценю, что вы нашли время, чтобы понять мой пример. – EvilDr

Смежные вопросы