在SQL Server中查询分隔的列值

时间:2012-05-21 14:36:04

标签: sql sql-server tsql

我想知道为什么这段代码没有返回任何结果

   SELECT A.PermissionGroupID, A.ApplicationID, CONVERT(nvarchar(5),A.PermissionID) AS Permission, A.PermissionName, B.PermissionGroupName, C.ApplicationName 
     FROM Permission AS A 
     JOIN PermissionGroup AS B ON A.PermissionGroupID = B.PermissionGroupID 
LEFT JOIN Application AS C ON A.ApplicationID = C.ApplicationID 
    WHERE (A.Active = 1) 
      AND (CONVERT(nvarchar(2),A.PermissionID) IN (SELECT Permissions 
                                                   FROM UserPermissions 
                                                   WHERE UserID = 1))

但是这个正在运作

   SELECT A.PermissionGroupID, A.ApplicationID, CONVERT(nvarchar(5),A.PermissionID) AS Permission, A.PermissionName, B.PermissionGroupName, C.ApplicationName 
     FROM Permission AS A 
     JOIN PermissionGroup AS B ON A.PermissionGroupID = B.PermissionGroupID 
LEFT JOIN Application AS C ON A.ApplicationID = C.ApplicationID 
    WHERE (A.Active = 1) 
      AND (CONVERT(nvarchar(2), A.PermissionID) IN ('5','6','7','8'))

这是我的权限表的内容

    Permission
--------------------------------
Permission   Permission    Application    Permission
ID           Group         ID             Name
4         1              1            VISA_APPLICATION_DELETE
5         1              1            VISA_APPLICATION_PRINT
6         4              10           APPLICATION_ADD   
7         4              10           APPLICATION_EDIT
8         4              10           APPLICATION_DELETE
9         4              10           APPLICATION_VIEW

以下是我的UserPermissions表的内容

UserPermissions
--------------------------
UserPermission      UserID    Permissions
ID
2           1         5,6,7,8   -> I tried to change it manually to this format ('5','6','7','8') but to no avail.

2 个答案:

答案 0 :(得分:1)

为什么我怀疑权限看起来像字符串“5,6,7,8”。我希望查询是“PermisionId in(从...中选择PermissionId)”,而不是(选择Permissions)。

假设是这种情况,以下版本的查询应该可以解决您的问题:

SELECT A.PermissionGroupID, A.ApplicationID, CONVERT(nvarchar(5),A.PermissionID) AS Permission,
       A.PermissionName, B.PermissionGroupName, C.ApplicationName
FROM Permission A JOIN
     PermissionGroup B
     ON A.PermissionGroupID = B.PermissionGroupID LEFT JOIN
     Application AS C
     ON A.ApplicationID = C.ApplicationID cross JOIN
     (SELECT Permissions
      FROM UserPermissions
      WHERE UserID = 1
     ) p1
WHERE (A.Active = 1) AND
      charindex(','+CONVERT(nvarchar(2)+',', A.PermissionID)+',', ','+p1.Permissions+',') > 0

注意我前缀并附加逗号,因此“1”与“15”不匹配。此外,这假设每个用户的UserPermissions只有一行。

顺便说一句,您应该修复您的架构,以便UserPermissions为每个用户和权限分别设置一行,这样您的原始配方就可以了。

答案 1 :(得分:0)

从评论中我发现你担心性能问题。性能问题是由于您存储逗号分隔的值字符串,每个值应该有一行 将表格UserPermissions更改为此类内容。

create table UserPermissions
(
  UserID int references Users(UserID),
  PermissionID int references Permission(PremissionID),
  primary key (UserID, PermissionID)
)

您的查询应该是......

SELECT A.PermissionGroupID,
       A.ApplicationID, 
       A.PermissionID,
       A.PermissionName,
       B.PermissionGroupName,
       C.ApplicationName 
FROM Permission AS A 
  JOIN PermissionGroup AS B 
    ON A.PermissionGroupID = B.PermissionGroupID 
  LEFT JOIN Application AS C 
    ON A.ApplicationID = C.ApplicationID 
WHERE A.Active = 1 AND 
      A.PermissionID IN (SELECT PermissionID 
                         FROM UserPermissions 
                         WHERE UserID = 1)