我正在使用一组表,这些表使用以下模式建立非规范化的位置结构:
Location (Name,Id)
Sublocation1 (Name,Id,LocationId)
Sublocation2 (Name,Id,Sublocation1Id)
Sublocation3 (Name,Id,Sublocation2Id)
跟踪用户与每个级别之间关联的表格:
UserLocation (User,LocationId,Sublocation1Id,Sublocation2Id,Sublocation3Id)
访问更高级别的位置可以访问其下的任何级别,因此以下示例中的第二行是多余的,但第三行不是:
User Location Sublocation1 Sublocation2 Sublocation3
----------------------------------------------------------------
Joe Houston Plant West Building NULL NULL
Joe Houston Plant West Building Third Floor Room 42
Joe Houston Plant East Building Second Floor Room 21
第三行授予Joe访问只是房间21,但不允许其访问二楼下的其他Sublocation3
问题:如何在不向Joe授予其他权限的情况下查找授予最高访问权限的所有记录?我的目标是能够从我的数据库中删除所有这些无关的条目。
我可以看到许多方法来解决这个问题,但我没有能够将其转化为基于集合的逻辑来进行良好的查询。
答案 0 :(得分:1)
我们假设UserLocation
表有一个Id
列。
如果不是,您可以使用ROW_NUMBER
生成一个。
为了识别strong
规则(与所有现有规则等效的现有访问规则的最小集合)或weak
规则(一组现有规则是多余的,因为它们也包含在内通过其他“更强大”的规则,您可以加入UserLocation
表格:
with access as (
select * from ( values
(1, 'Joe', 'Houston Plant', 'West Building', NULL, NULL ),
(2, 'Joe', 'Houston Plant', 'West Building', 'Third Floor', 'Room 42'),
(3, 'Joe', 'Houston Plant', 'East Building', 'Second Floor', 'Room 21'),
(4, 'Mark', 'Houston Plant', 'West Building', NULL, NULL ),
(5, 'Mark', 'Houston Plant', 'West Building', 'Third Floor', 'Room 42'),
(6, 'Mark', 'Houston Plant', 'West Building', 'Second Floor', 'Room 21'),
(7, 'Bob', null, null, NULL, NULL ),
(8, 'Bob', 'Houston Plant', 'West Building', 'Third Floor', 'Room 42'),
(9, 'Bob', 'Houston Plant', 'West Building', 'Second Floor', 'Room 21')
) as v(Id, Usr, Location1, Location2, Location3, Location4)
)
select distinct
weak.* -- or strong.*
from access strong
inner JOIN
access weak on weak.Usr = strong.Usr
and weak.Id <> strong.Id
and (strong.Location1 is null or weak.Location1 = strong.Location1)
and (strong.Location2 is null or weak.Location2 = strong.Location2)
and (strong.Location3 is null or weak.Location3 = strong.Location3)
and (strong.Location4 is null or weak.Location4 = strong.Location4)
修改强>
我发现可能存在对用户来说唯一的规则:
(10, 'John', 'Houston Plant', 'West Building', 'Third Floor', 'Room 42'),
(11, 'Ana', 'Houston Plant', 'West Building', NULL, NULL )
由于上述查询使用了INNER JOIN
,因此这些规则不会在任何集合(weak
或strong
)中报告,但如果您考虑一下,可以认为这些规则是{{可以这么说因为:
答案 1 :(得分:1)
鉴于下表:
CREATE TABLE UserLocation(
UserId int,
LocationId int,
Sublocation1Id int,
Sublocation2Id int,
Sublocation3Id int
)
以下查询为您提供最高级别的访问权限:
-- Highest level access:
SELECT * -- Level 3 grants with no higher level grants
FROM UserLocation UL
WHERE
UL.Sublocation3Id IS NOT NULL
AND NOT EXISTS (
SELECT * -- higher level grant
FROM UserLocation UL1
WHERE
UL1.Sublocation3Id IS NULL
AND (UL1.Sublocation2Id IS NULL OR UL1.Sublocation2Id = UL.Sublocation2Id)
AND (UL1.Sublocation1Id IS NULL OR UL1.Sublocation1Id = UL.Sublocation1Id)
AND (UL1.LocationId = UL.LocationId)
)
UNION ALL
SELECT * -- Level 2 grants with no higher level grants
FROM UserLocation UL
WHERE
UL.Sublocation3Id IS NULL
AND UL.Sublocation2Id IS NOT NULL
AND NOT EXISTS (
SELECT * -- higher level grant
FROM UserLocation UL1
WHERE
UL1.Sublocation3Id IS NULL
AND UL1.Sublocation2Id IS NULL
AND (UL1.Sublocation1Id IS NULL OR UL1.Sublocation1Id = UL.Sublocation1Id)
AND (UL1.LocationId = UL.LocationId)
)
UNION ALL
SELECT * -- Level 1 grants with no higher level grants
FROM UserLocation UL
WHERE
UL.Sublocation3Id IS NULL
AND UL.Sublocation2Id IS NULL
AND UL.Sublocation1Id IS NOT NULL
AND NOT EXISTS (
SELECT * -- higher level grant
FROM UserLocation UL1
WHERE
UL1.Sublocation3Id IS NULL
AND UL1.Sublocation2Id IS NULL
AND UL1.Sublocation1Id IS NULL
AND (UL1.LocationId = UL.LocationId)
)
SELECT * -- Level 0 grants
FROM UserLocation UL
WHERE
UL.Sublocation3Id IS NULL
AND UL.Sublocation2Id IS NULL
AND UL.Sublocation1Id IS NULL
以下查询显示了超级拨款:
-- Superflous grants (there is higher level grants)
SELECT * -- Level 3 grants with higher level grants
FROM UserLocation UL
WHERE
UL.Sublocation3Id IS NOT NULL
AND EXISTS (
SELECT * -- higher level grant
FROM UserLocation UL1
WHERE
UL1.Sublocation3Id IS NULL
AND (UL1.Sublocation2Id IS NULL OR UL1.Sublocation2Id = UL.Sublocation2Id)
AND (UL1.Sublocation1Id IS NULL OR UL1.Sublocation1Id = UL.Sublocation1Id)
AND (UL1.LocationId = UL.LocationId)
)
UNION ALL
SELECT * -- Level 2 grants with higher level grants
FROM UserLocation UL
WHERE
UL.Sublocation3Id IS NULL
AND UL.Sublocation2Id IS NOT NULL
AND EXISTS (
SELECT * -- higher level grant
FROM UserLocation UL1
WHERE
UL1.Sublocation3Id IS NULL
AND UL1.Sublocation2Id IS NULL
AND (UL1.Sublocation1Id IS NULL OR UL1.Sublocation1Id = UL.Sublocation1Id)
AND (UL1.LocationId = UL.LocationId)
)
UNION ALL
SELECT * -- Level 1 grants with higher level grants
FROM UserLocation UL
WHERE
UL.Sublocation3Id IS NULL
AND UL.Sublocation2Id IS NULL
AND UL.Sublocation1Id IS NOT NULL
AND EXISTS (
SELECT * -- higher level grant
FROM UserLocation UL1
WHERE
UL1.Sublocation3Id IS NULL
AND UL1.Sublocation2Id IS NULL
AND UL1.Sublocation1Id IS NULL
AND (UL1.LocationId = UL.LocationId)
)
我假设如果位置级别L
的id为null,则位置级别L+1
的id为空。