Sql server 查找';缺失';跨两个结果集的行
我已经为此挣扎了好几天,所以如果我把事情弄糊涂了,我道歉 我有一系列表,这些表定义:Sql server 查找';缺失';跨两个结果集的行,sql-server,tsql,sql-server-2012,Sql Server,Tsql,Sql Server 2012,我已经为此挣扎了好几天,所以如果我把事情弄糊涂了,我道歉 我有一系列表,这些表定义: 技能组 技巧 上述群体中的技能(多对多) 工作角色 这些工作角色的技能(多对多) 数据库的结构如下所示: 我需要创建一个显示以下数据的结果集: 对于所有工作角色,展示这些工作中的所有技能 角色。但是,还应包括各自小组内的技能 未包含在每个角色中(用NULL或任何 其他方法) 请参阅此工作代码以创建表和数据 抱歉篇幅太长,我做了很多插入来创建一个现实的例子 请注意,PowerPoint技能不会添加到人力资源经理
抱歉篇幅太长,我做了很多插入来创建一个现实的例子 请注意,
PowerPoint
技能不会添加到人力资源经理的角色中,但会添加来自同一组的其他技能。还请注意,招聘政策
技能未添加到软件经理
角色中,但我不需要看到此差距,因为该角色中不存在该组中的其他技能
我希望得到的结果与此类似(为了简洁起见,不包括超级明星角色):
roletitlegrouptitle SkillTitle SkillIsInRole
----------------------- -------------------------- --------------------------------------
软件经理Microsoft Office Excel 1
软件经理Microsoft Office Word 1
软件经理Microsoft Office PowerPoint 1
软件管理器Microsoft SQL Server查询设计1
软件管理器Microsoft SQL Server存储过程1
软件管理器Microsoft SQL Server故障转移群集1
人力资源经理Microsoft Office Excel 1
人力资源经理Microsoft Office Word 1
人力资源经理Microsoft Office PowerPoint NULL我认为您必须准备一套所有可能的组合:一方的角色和另一方的团队技能。这是通过进行Decart乘法实现的(通常通过交叉连接实现)。因此,您将拥有一份每个角色的列表,以及一份所有可能的团队技能组合的列表。之后,您可以将此结果与表tbl_RolesSkills左连接。这会给你所需要的。您可以通过使用CTE或子查询来实现这一点
必须看起来像
实际上不需要交叉连接,我遗漏了“特定角色只有特定组集”的部分。只有一个子查询,也可以使用CTE(公共表表达式)完成
我还排除了“超级明星”的角色。如果要添加它,只需删除WHERE部分。获取与角色相关的组的所有技能有点简单,可以在下面相对自解释的角色中处理。从这一点上,我能想到的获取技能是否与角色“直接”相关的唯一方法是通过OUTER将结果集应用到角色的实际技能的结果集
;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
编辑:外部应用
可以通过左连接处理
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
谢谢。你能在SQL Fiddle脚本中发布一个例子吗?对不起,我在iPad上写答案,在上面写脚本对我来说很难:)太好了。非常感谢你。非常感谢你花时间理解我的例子。非常感谢。明天早上我回来工作的时候我会试试。棒极了。非常感谢。我会浏览你们的“tba”网站,当你们在找新工作时,我会检查我们的财务状况是否允许:-)请回答一个简单的问题。您的查询执行速度比Bogdan快一小部分,但代码却多得多。你知道为什么会这样吗?我选择您的答案是正确的,完全是因为这个原因。您在哪里检查了两个查询的执行时间?我并不是说我的速度更快,我认为他们必须有相似的执行时间。我检查了测试数据的SMSS客户端统计信息。你的回答慢了一点,但只差一小部分。我认为你的答案更容易阅读,我在工作中也用到了。
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