2014-10-31 63 views
1

我有下面的表结构更好的方法来写这个SQL查询

用户(PK - 用户ID)
系统(PK - SYSTEMID)
SystemRoles(PK-SystemRoleId,FK - SYSTEMID)
的UserRole(PK-用户ID & SystemRoleId,FK-SystemRoleId,FK-用户Id)

Users可以访问不同Systems和一个System可以定义不同的SystemRoles

现在,我需要删除Users谁有SystemRoles分配给他们只为一个特定的System(s)。如果他们为其他Systems定义了SystemRoles,则不应删除它们。

我已经拿出下面的查询来标识符合删除条件的记录,但认为这肯定会被优化。有什么建议么?

SELECT U.* 
FROM 
(
    SELECT 
     distinct UR.UserID 
    FROM 
     dbo.UserRole UR 
     INNER JOIN dbo.SystemRole SR ON (SR.SystemRoleID = UR.SystemRoleID) 
     INNER JOIN dbo.[System] S ON (S.SystemID = SR.SystemID) 
    WHERE 
     S.SystemName = 'ABC' OR S.SystemName = 'XYZ' 
) T 
INNER JOIN dbo.[User] U ON (U.UserID = T.UserID) 
WHERE T.UserID NOT IN 
(
    select 
     distinct UR.UserID 
    from 
     dbo.[UserRole] UR 
     INNER JOIN dbo.SystemRole SR ON (SR.SystemRoleID = UR.SystemRoleID) 
     INNER JOIN dbo.[System] S ON (S.SystemID = SR.SystemID) 
    WHERE 
     S.SystemName <> 'ABC' 
    AND S.SystemName <> 'XYZ' 
) 
+0

它有什么问题?它慢吗?你确定它很慢吗?如果它没有损坏... – DLeh 2014-10-31 16:18:34

+0

如果没有任何问题,也许http://codereview.stackexchange.com是一个更好的去处。 – DLeh 2014-10-31 16:19:13

+0

你还没有忘记添加索引,对不对?特别是对于唯一的ID – 2014-10-31 16:20:46

回答

1

这种结构将为您提供所需的记录。

select yourfields -- or delete 
from userroles 
where userid in 
(select userid 
from userroles join etc 
where system.name = the one you want 
except 
select userid 
from userroles join etc 
where system.name <> the one you want 
) 
3

这样的事情?

select userid from (
     SELECT 
      UR.UserID, 
      max(case when (S.SystemName = 'ABC' OR S.SystemName = 'XYZ') 
       then 1 else 0 end) as kill, 
      max(case when (S.SystemName <> 'ABC' AND S.SystemName <> 'XYZ') 
       then 1 else 0 end) as keep 
     FROM 
      dbo.UserRole UR 
      INNER JOIN dbo.SystemRole SR ON (SR.SystemRoleID = UR.SystemRoleID) 
      INNER JOIN dbo.[System] S ON (S.SystemID = SR.SystemID) 
     group by UR.UserID 
) u where kill = 1 and keep = 0 
+0

正好符合我将与...运行...很好,干净。一次通过,检查两者。我会稍微改变最大值(条件/ 1/0的情况下)和最大值(NOT条件/ 1/0的情况下),这就是其他。 – DRapp 2014-10-31 17:14:14

+0

为方法。与进行2次通过检查相比,在性能方面没有区别。两者都在一秒内返回约200,000条记录。执行计划在系统表上显示索引扫描,而对于另一个查询则为索引搜索。这对我来说肯定不是问题,因为System表中只有不到50行,我不知道如果System表有几千行,这个查询将如何执行。 – 2014-11-03 11:45:36

相关问题