Jer*_*emy 0 sql sql-server hierarchyid sql-server-2008
我使用HierarchyId数据类型来存储位置.用户可能受location(LocationId)的限制.如果用户具有多个位置限制,则必须使用a再次调用HierarchyId数据类型上的IsDescendantOf方法OR.
示例(按位置5和6筛选员工):
SELECT * FROM Employee
INNER JOIN Location ON Employee.LocationId = Location.LocationId
WHERE Location.Node.IsDescendantOf((SELECT TOP 1 Node
FROM Location
WHERE LocationId = 5)) = 1
OR
Location.Node.IsDescendantOf((SELECT TOP 1 Node
FROM Location
WHERE LocationId=6)) = 1`
Run Code Online (Sandbox Code Playgroud)
这适用于2个LocationId过滤器,但如果这种情况增长并且一个人说10个过滤器会怎样.IsDescendantOf可以像sql IN子句一样工作吗?
使用的表:
CREATE TABLE Location (
LocationId int NOT NULL PRIMARY KEY IDENTITY(1,1),
Name nvarchar(100) NOT NULL,
[Node] hierarchyid NOT NULL,
[ParentNode] AS ([Node].[GetAncestor]((1))) PERSISTED,
[Level] AS ([Node].[GetLevel]()) PERSISTED,
);
CREATE TABLE [dbo].[Employee] (
[EmployeeId] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL,
[LocationId] [int] NULL,
[Name] [nvarchar](50) NULL
) ;
Run Code Online (Sandbox Code Playgroud)
注意:我加入了第二个解决方案(第6点).
1)您可以使用表变量来存储所有搜索的位置(例如DECLARE @SearchedAncestorLocation TABLE(LocationId INT PRIMARY KEY)).
2)您必须HIERARCHYID's为每个位置ID 找到节点@SearchedAncestorLocation.
3)您必须INNER JOIN使用此过滤器对员工的位置进行操作:employee_location.Node.IsDescendantOf(searched_location.Node) = 1.
4)我认为你应该UNIQUE(Node)在Location表中添加一个约束来防止重复的位置(重复的节点).
5)第一个解决方案:这里演示.
DECLARE @Location TABLE(
LocationId int NOT NULL PRIMARY KEY,
Name nvarchar(100) NOT NULL,
[Node] hierarchyid NOT NULL,
UNIQUE ([Node])
);
DECLARE @Employee TABLE (
[EmployeeId] [int] PRIMARY KEY,
[LocationId] [int] NULL,
[Name] [nvarchar](50) NULL
);
INSERT @Location(LocationId, Name, [Node])
VALUES ( 1, N'A', '/1/'),
( 2, N'AA', '/1/1/'),
( 3, N'AA-1', '/1/1/1/'), -- <-- First employee @ AA-1
( 4, N'AA-2', '/1/1/2/'),
( 5, N'AA-3', '/1/1/3/'),
( 6, N'AB', '/1/2/'),
( 7, N'AA-1', '/1/2/1/'),
( 8, N'AB-2', '/1/2/2/'),
( 9, N'B', '/2/'),
(10, N'BA', '/2/1/'),
(11, N'BA-1', '/2/1/1/'), -- <-- Second employee @ BA-1
(12, N'BA-2', '/2/1/2/'),
(13, N'BA-3', '/2/1/3/'),
(14, N'BB', '/2/2/'),
(15, N'BB-1', '/2/2/1/');
INSERT @Employee(EmployeeId, [Name], LocationId)
VALUES (1, N'Ion Ionescu', 3), -- AA-1
(2, N'Geo Georgescu', 11); -- BA-1
DECLARE @SearchedAncestorLocation TABLE(LocationId INT PRIMARY KEY);
INSERT @SearchedAncestorLocation
VALUES (1), --A
(2), --AA
(3), --AA-1
(9), --B
(10), --BA
(14); --BB
SELECT e.*,
el.Name AS EmpLocationName,
el.Node.ToString() AS EmpLocationHID,
s.LocationId AS SearchedLocationId,
sl.Name AS SearchedLocationName,
sl.Node.ToString() AS SearchedLocationHID
FROM @Employee e
INNER JOIN @Location el ON e.LocationId = el.LocationId
INNER JOIN @Location sl ON el.Node.IsDescendantOf(sl.Node) = 1
INNER JOIN @SearchedAncestorLocation s ON sl.LocationId = s.LocationId
--AND sl.Node <> el.Node
Run Code Online (Sandbox Code Playgroud)
结果:
EmployeeId LocationId Name EmpLocationName EmpLocationHID SearchedLocationId SearchedLocationName SearchedLocationHID
---------- ----------- ------------- --------------- -------------- ------------------ -------------------- -------------------
1 3 Ion Ionescu AA-1 /1/1/1/ 1 A /1/
1 3 Ion Ionescu AA-1 /1/1/1/ 2 AA /1/1/
1 3 Ion Ionescu AA-1 /1/1/1/ 3 AA-1 /1/1/1/
2 11 Geo Georgescu BA-1 /2/1/1/ 9 B /2/
2 11 Geo Georgescu BA-1 /2/1/1/ 10 BA /2/1/
Run Code Online (Sandbox Code Playgroud)
结果如果取消注释最后一行(AND sl.Node <> el.Node):
EmployeeId LocationId Name EmpLocationName EmpLocationHID SearchedLocationId SearchedLocationName SearchedLocationHID
---------- ----------- ------------- --------------- -------------- ------------------ -------------------- -------------------
1 3 Ion Ionescu AA-1 /1/1/1/ 1 A /1/
1 3 Ion Ionescu AA-1 /1/1/1/ 2 AA /1/1/
2 11 Geo Georgescu BA-1 /2/1/1/ 9 B /2/
2 11 Geo Georgescu BA-1 /2/1/1/ 10 BA /2/1/
Run Code Online (Sandbox Code Playgroud)
6)第二种解决方案.
SELECT e.EmployeeId,
e.LocationId,
e.Name
FROM @Employee e
INNER JOIN @Location el ON e.LocationId = el.LocationId
WHERE EXISTS
(
SELECT *
FROM @SearchedAncestorLocation s
INNER JOIN @Location sl ON s.LocationId = sl.LocationId
WHERE el.Node.IsDescendantOf(sl.Node) = 1
--AND el.Node <> sl.Node
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4338 次 |
| 最近记录: |