我正在处理的项目有7个级别的业务层次结构。它们都不属于同一类型。这意味着,这不是组织结构图,所有项目都是某种级别的员工。他们是分部,地区,销售副总裁,业务部门等。是的,其中一些可能是员工,但不是全部。
目前,我在他们自己的表中各自遵循相似的模式,每个孩子都有一个父母的外键。所以从层次结构的最小部分开始:
ID
Name
AreaManagerID
ID
Name
RegionalManagerID
ID
Name
DivisionID
ID
Name
还有3个表混合在一起,但这应该显示层次结构的每个级别之间相当简单的链接。每个孩子都必须有父母。不会有任何没有BusinessUnits的AreaManager。
在HierarchyID上读一点我不完全确定它会对我有所帮助。
我知道上面的作品,很好。但是当我被赋予一个部门并且需要找到其中的所有BU时,我更想知道是否有更好的方法和/或更快的方式。或者甚至被赋予一个区域并且需要找到其中的所有BU。
答案 0 :(得分:0)
如果你正在寻找"给我后代",HierarchyID非常快速地找到任意深度的后代。如果你这样做,我会将所有实体放在一个表中,其中包含不同类型的分组表。看起来有点像这样:
CREATE TABLE [dbo].[BusinessEntity] (
[EntityID] INT IDENTITY NOT NULL PRIMARY KEY,
[ParentEntityID] INT
REFERENCES [dbo].[BusinessEntity] ([EntityID]),
[EntityType] TINYINT NOT NULL,
[Path] HIERARCHYID
);
CREATE TABLE [dbo].[BusinessUnit] (
[ID] INT NOT NULL PRIMARY KEY
REFERENCES [dbo].[BusinessEntity] ([EntityID]),
[Name] VARCHAR(255) NOT NULL,
[AreaManagerID] INT NOT NULL
);
CREATE TABLE [dbo].[AreaManager] (
[ID] INT NOT NULL PRIMARY KEY
REFERENCES [dbo].[BusinessEntity] ([EntityID]),
[Name] VARCHAR(255) NOT NULL,
[RegionalManagerID] INT NOT NULL
);
CREATE TABLE [dbo].[RegionalManager] (
[ID] INT NOT NULL PRIMARY KEY
REFERENCES [dbo].[BusinessEntity] ([EntityID]),
[Name] VARCHAR(255) NOT NULL,
[DivisionID] INT NOT NULL
);
CREATE TABLE [dbo].[Division] (
[ID] INT NOT NULL PRIMARY KEY
REFERENCES [dbo].[BusinessEntity] ([EntityID]),
[Name] VARCHAR(255)
);
当您要插入其中一个实际表格(例如BusinessUnit,RegionalManager等)时,您首先要在BusinessEntity中创建一条记录,然后使用生成的标识值作为插入的标识符。您还需要使路径列与层次结构中的关系保持同步。也就是说,让我们说我在BusinessEntity中有以下数据:
SET IDENTITY_INSERT [dbo].[BusinessEntity] ON;
INSERT INTO [dbo].[BusinessEntity]
( [EntityID],
[ParentEntityID] ,
[EntityType]
)
VALUES
(1, NULL, 1),
(2, 1, 2),
(3, 1, 2),
(4, 2, 3),
(5, 3, 3),
(6, 4, 4),
(7, 6, 5);
然后我可以使用以下CTE生成Path值
WITH cte AS (
SELECT [be].[EntityID], [be].[ParentEntityID], CAST(CONCAT('/', [be].[EntityID], '/') AS VARCHAR(MAX)) AS [Path]
FROM [dbo].[BusinessEntity] AS [be]
WHERE [be].[ParentEntityID] IS null
UNION ALL
SELECT [child].[EntityID], [child].[ParentEntityID], CAST(CONCAT([parent].[Path], child.[EntityID], '/') AS VARCHAR(MAX))
FROM [dbo].[BusinessEntity] AS [child]
JOIN [cte] AS [parent]
ON [child].[ParentEntityID] = [parent].[EntityID]
)
UPDATE [be]
SET [be].[Path] = cte.[Path]
FROM [dbo].[BusinessEntity] AS be
JOIN cte
ON [be].[EntityID] = [cte].[EntityID]
WHERE [Path] IS NULL;
当然,保持更新它们要容易得多。当您插入新行时,从父行抓取路径,将ID添加到其中,这就是您的路径。更新行的父级有点棘手,但并不可怕。我将它作为练习留给读者。但作为提示,它涉及HierarchyID数据类型的GetReparentedValue()
方法。最后,如果你不相信Path中的值(因为它是派生值),你可以设置你不信任的任何值为NULL并重新运行上面的cte更新。