我们有一个包含Widgets表的数据库。每个Widget只能由具有正确角色的用户查看。可以授予多个角色查看每个窗口小部件的权限。
表格如下:
的widget
Widget_Id
1
权限
Widget_Id | Role_Id
1 | 1
1 | 2
角色
Role_Id | User_Id
1 | 1
2 | 1
用户
User_Id
1
现在让我们说我想找到允许给定用户看到的所有小部件:
SELECT *
FROM Widget
JOIN Permission USING(Widget_Id)
WHERE Role_Id IN (
SELECT Role_Id
FROM Role
JOIN User
WHERE User_Id = 1)
这里的问题是Widget被授予了几个角色,而用户拥有多个角色。如何阻止查询返回同一个Widget的多个重复项,每个角色一个? (请注意,我不想使用DISTINCT
或ROW_NUMBER OVER(PARTITION...)
技巧。我发现大表的性能会显着降低。
答案 0 :(得分:3)
使用WHERE EXISTS
构造。这可以保证您不会看到重复的小部件。
SELECT * FROM Widget w
WHERE EXISTS
(SELECT 1 FROM Permission p
JOIN Role r ON r.Role_ID = p.Role_ID
JOIN User u ON u.User_ID = r.User_ID
WHERE p.Widget_ID = w.Widget_ID
AND u.User_ID = ?)
答案 1 :(得分:1)
如果您的架构如下:
create table Widget (Widget_Id int, Widget_Name varchar(50));
create table Permission (Widget_Id int,Role_Id int);
Create table Roles (Role_Id int, [User_Id] int);
Create table Users ([User_Id] int, [User_Name] varchar(50));
go
数据样本如下:
insert into WIDGET Values(1, 'W1');
insert into WIDGET Values(2, 'W2');
insert into PERMISSION Values(1,1);
insert into PERMISSION Values(1,2);
Insert into ROLES Values(1,1);
Insert into ROLES Values(2,1);
Insert into USERS Values(1,'U1');
Insert into USERS Values(2,'U2');
Go
为给定用户提供单组允许小部件的脚本将是:
SELECT *
FROM Widget W
WHERE W.WIDGET_ID IN (
SELECT P.WIDGET_ID
FROM Roles R
JOIN Permission P on R.ROLE_ID=P.ROLE_ID
JOIN Users U ON R.USER_ID=U.USER_ID
WHERE U.User_Id = 1)