我有用户列表。对于每个用户,由字段ParentId定义了层次结构(少数用户位于层次结构之上 - 它们在此字段中为空)。我不想更改此表的结构(并添加exaple hierarchyId到表)。
此刻我有这张桌子:
用户:
UserId INT NOT NULL, ManagerId INT NULL, other fields
我需要创建所有关系用户 - 祖先的列表以及这些用户之间的级别差异:
UserId, AncestorId, LevelDifference
例:
来自用户表:
UserId INT NOT NULL,ManagerId INT NULL
1,NULL,(吉姆)
2,1(约什)
3,2(珍妮)
我应该得到:
UserId,AncestorId,LevelDifference
2,1,1
3,2,1
3,1,2 - (吉姆是珍妮的祖先之一)
有没有人知道如何快速地做到这一点?
答案 0 :(得分:3)
更新 - 这应该是您所寻找的。 使用递归CTE,如Joe Stefanelli所说:
表格结构:
CREATE TABLE [HR].[Employees](
[empid] [int] IDENTITY(1,1) NOT NULL,
[lastname] [nvarchar](20) NOT NULL,
[firstname] [nvarchar](10) NOT NULL,
[mgrid] [int] NULL
);
我使用的示例数据:
empid lastname firstname mgrid
----------- -------------------- ---------- -----------
1 Davis Sara NULL
2 Funk Don 1
3 Lew Judy 2
4 Peled Yael 3
5 Buck Sven 2
6 Suurs Paul 5
7 King Russell 5
8 Cameron Maria 3
9 Dolgopyatova Zoya 5
查询:
WITH RCTE AS (
SELECT NULL AS PrevEmpId,
NULL AS PrevMgrId,
E.empid AS CurEmpId,
E.mgrid AS CurMgrid,
0 AS [Level],
E.lastname AS LastName,
E.firstname AS FirstName
FROM HR.Employees AS E
WHERE E.mgrid IS NULL
UNION ALL
SELECT PREV.CurEmpId AS PrevEmpId,
PREV.CurMgrid AS PrevMgrId,
CUR.empid AS CurEmpId,
CUR.mgrid AS CurMgrId,
Prev.Level + 1 AS [Level],
CUR.lastname AS LastName,
CUR.firstname AS FirstName
FROM RCTE AS PREV
JOIN HR.Employees AS CUR ON CUR.mgrid = PREV.CurEmpId
),RAnecestors AS (
SELECT E.empid AS StartEmpId,
NULL AS PrevEmpId,
NULL AS PrevMgrId,
E.empid AS CurEmpId,
E.mgrid AS CurMgrid,
1 AS [LevelDiff],
E.lastname AS LastName,
E.firstname AS FirstName
FROM HR.Employees AS E
UNION ALL
SELECT PREV.StartEmpId AS StartEmpId,
PREV.CurEmpId AS PrevEmpId,
PREV.CurMgrid AS PrevMgrId,
CUR.empid AS CurEmpId,
CUR.mgrid AS CurMgrId,
Prev.[LevelDiff] + 1 AS [LevelDiff],
CUR.lastname AS LastName,
CUR.firstname AS FirstName
FROM RAnecestors AS PREV
JOIN HR.Employees AS CUR ON CUR.empid = PREV.CurMgrid
)
SELECT RCTE.CurEmpId AS CurrentID,
RCTE.LastName AS CurrentLastName,
RAnecestors.CurEmpId AS AncestorID,
RAnecestors.LastName AS AncestorLastName,
[Level] AS [Level],
[LevelDiff] - 1 AS [LevelDiff]
LEFT JOIN RAnecestors ON RAnecestors.StartEmpId = RCTE.CurEmpId
AND RCTE.CurEmpId <> RAnecestors.CurEmpId
ORDER BY RCTE.CurEmpId, RAnecestors.LevelDiff
输出:
CurrentID CurrentLastName AncestorID AncestorLastName Level LevelDiff
----------- -------------------- ----------- -------------------- ----------- -----------
1 Davis NULL NULL 0 NULL
2 Funk 1 Davis 1 1
3 Lew 2 Funk 2 1
3 Lew 1 Davis 2 2
4 Peled 3 Lew 3 1
4 Peled 2 Funk 3 2
4 Peled 1 Davis 3 3
5 Buck 2 Funk 2 1
5 Buck 1 Davis 2 2
6 Suurs 5 Buck 3 1
6 Suurs 2 Funk 3 2
6 Suurs 1 Davis 3 3
7 King 5 Buck 3 1
7 King 2 Funk 3 2
7 King 1 Davis 3 3
8 Cameron 3 Lew 3 1
8 Cameron 2 Funk 3 2
8 Cameron 1 Davis 3 3
9 Dolgopyatova 5 Buck 3 1
9 Dolgopyatova 2 Funk 3 2
9 Dolgopyatova 1 Davis 3 3
答案 1 :(得分:1)
我不会在SQL中这样做。只使用sql获取祖先用户列表很容易,但我不确定如何在没有tree
结构的情况下计算leveldifference。我不是说你不能用sql做到这一点,我只是不知道解决方案。
我会将您的用户置于树数据结构中。从那里可以更容易地获得水平差异(子树的高度)。