是否可以仅选择具有管理员角色(角色ID = 3)的用户的id而不使用NOT IN(与roleid相同的查询)?
每个用户都有不同的角色(用户,经理,管理员等)。
SELECT appUserInGroups.UserId, appRoles.RoleName, appRoles.RoleId
FROM appGroupInRoles
INNER JOIN appRoles ON appGroupInRoles.RoleId = appRoles.RoleId
INNER JOIN appUserInGroups ON appGroupInRoles.GroupId = appUserInGroups.GroupId
INNER JOIN appApplications ON appRoles.ApplicationId = appApplications.ApplicationId
WHERE appGroupInRoles.UserId not in ( SELECT appUserInGroups.UserId
FROM appGroupInRoles
INNER JOIN appRoles ON appGroupInRoles.RoleId = appRoles.RoleId
INNER JOIN appUserInGroups ON appGroupInRoles.GroupId = appUserInGroups.GroupId
INNER JOIN appApplications ON appRoles.ApplicationId = appApplications.ApplicationId
WHERE appGroupInRoles.RoleId = 3)
NOT IN完全杀死了性能。
用户角色预览:
答案 0 :(得分:2)
试试这个:
WITH Admins AS
(
SELECT appUserInGroups.UserId AS uID
FROM appGroupInRoles
INNER JOIN appUserInGroups ON appGroupInRoles.GroupId = appUserInGroups.GroupId
WHERE appGroupInRoles.RoleId = 3
)
SELECT appUserInGroups.UserId, appRoles.RoleName, appRoles.RoleId
FROM appGroupInRoles
INNER JOIN appRoles ON appGroupInRoles.RoleId = appRoles.RoleId
INNER JOIN appUserInGroups ON appGroupInRoles.GroupId = appUserInGroups.GroupId
INNER JOIN appApplications ON appRoles.ApplicationId = appApplications.ApplicationId
LEFT JOIN Admins on appGroupInRoles.UserId = Admins.uID
WHERE Admins.uID is null
我从子查询中删除了一些额外的连接,并将其添加为CTE。我还使用了一个左连接而不是in(实际上应该在执行计划中编译相同)但添加它以向您显示“另一种方式”。
如果优化器运行良好,它应具有与以下相同的确切执行计划。
SELECT appUserInGroups.UserId, appRoles.RoleName, appRoles.RoleId
FROM appGroupInRoles
INNER JOIN appRoles ON appGroupInRoles.RoleId = appRoles.RoleId
INNER JOIN appUserInGroups ON appGroupInRoles.GroupId = appUserInGroups.GroupId
INNER JOIN appApplications ON appRoles.ApplicationId = appApplications.ApplicationId
WHERE appGroupInRoles.UserId NOT IN (
SELECT appUserInGroups.UserId AS uID
FROM appGroupInRoles
INNER JOIN appUserInGroups ON appGroupInRoles.GroupId = appUserInGroups.GroupId
WHERE appGroupInRoles.RoleId = 3
)
编辑:请参阅评论中的链接以获取一篇很好的帖子,解释为什么您应该始终在SQL Server上使用NOT EXISTS。随机附注;根据我的经验,你应该在DB2上使用NOT IN
答案 1 :(得分:1)
尝试排除加入:
SELECT u.UserId, r.RoleName, r.RoleId
FROM appUserInGroups u
INNER JOIN appGroupInRoles g on g.GroupId = u.GroupId
INNER JOIN appRoles r ON r.RoleId = g.RoleId
LEFT JOIN (
--Admin Users
SELECT u.UserId
FROM appUserInGroups u
INNER JOIN appGroupInRoles g on g.GroupId = u.GroupId and g.RoleID=3
) a on a.UserId = u.UserId
WHERE a.UserId IS NULL
不确定你在使用appApplications
表做了什么,看起来你在桌子上看的顺序有点奇怪......就像你从中间开始一样。
使用NOT EXISTS
查询,您或许可以做得更好。
答案 2 :(得分:0)
您可以使用分析功能告诉您用户是否有角色3.但我不知道这是否更快。
select distinct userid, rolename, roleid
from
(
SELECT
appUserInGroups.UserId,
appRoles.RoleName,
appRoles.RoleId,
max(case when appRoles.RoleId = 3 then 1 else 0 end) over (partition by appUserInGroups.UserId) as has3
FROM appGroupInRoles
INNER JOIN appRoles ON appGroupInRoles.RoleId = appRoles.RoleId
INNER JOIN appUserInGroups ON appGroupInRoles.GroupId = appUserInGroups.GroupId
INNER JOIN appApplications ON appRoles.ApplicationId = appApplications.ApplicationId
)
where has3 = 0;
我还添加了DISTINCT,因为用户可以通过不同组的成员身份获得角色,因此您可以在不使用DISTINCT的情况下获得重复项。