如何从SQL表中检索层次结构数据 [英] How to retrieve hierarchical data from SQL table

查看:60
本文介绍了如何从SQL表中检索层次结构数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个表:T_Employees和T_Projects

I have 2 tables : T_Employees and T_Projects

每个项目都分配了不同数量的员工.我需要做的是获取分配给特定项目的每个员工的层次结构.

Every project has different number of employees assigned. What i need to do, is to get hierarchical structure of each employee, assigned to a specific project.

看下面的图片和预期的结果.

Look at the image below and the expected results.

如何在Microsoft SQL Server 2008R2上完成此操作?

How to get this done on Microsoft SQL Server 2008R2?

CREATE TABLE [dbo].[T_Projects](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [ProjectId] [int] NOT NULL,
    [EmployeeId] [int] NOT NULL,
    CONSTRAINT [PK_T_Projects] PRIMARY KEY CLUSTERED([ID] ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY] 
GO

SET IDENTITY_INSERT [dbo].[T_Projects] ON
INSERT [dbo].[T_Projects] ([ID], [ProjectId], [EmployeeId]) VALUES (1, 456,10)
INSERT [dbo].[T_Projects] ([ID], [ProjectId], [EmployeeId]) VALUES (2, 456, 12)
INSERT [dbo].[T_Projects] ([ID], [ProjectId], [EmployeeId]) VALUES (3, 23, 11)
SET IDENTITY_INSERT [dbo].[T_Projects] OFF

CREATE TABLE [dbo].[T_Employees](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Level] [int] NOT NULL,
    [Employee] [nvarchar](256) NOT NULL,
    [Department] [nvarchar](5) NOT NULL,
    [MasterId] [int] NULL,
    [Code] [nvarchar](10) NOT NULL,
    [Note] [nvarchar](100) NULL,
    CONSTRAINT [PK_T_Employees] PRIMARY KEY CLUSTERED ([ID] ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]) ON [PRIMARY]
GO

SET IDENTITY_INSERT [dbo].[T_Employees] ON
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (1, 1, N'Thomas S.', N'A', NULL, N'1-4', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (2, 1, N'Michael F.', N'A', NULL, N'1-5', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (3, 1, N'Simone S.', N'A', NULL, N'1-3', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (4, 2, N'Stefan K.', N'B', 1, N'2-18', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (5, 2, N'Mike T.', N'B', 2, N'2-96', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (6, 2, N'Loris P.', N'B', 3, N'2-15', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (7, 3, N'Lennon I.', N'B', 4, N'2-19', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (8, 3, N'Kerim K.', N'C', 4, N'2-66', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (9, 3, N'Ilmas Y.', N'C', 6, N'2-59', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (10, 4, N'Innes Y.', N'D', 8, N'3-89', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (11, 4, N'Andreas U.', N'E', 7, N'3-63', NULL)
INSERT [dbo].[T_Employees] ([ID], [Level], [Employee], [Department], [MasterId], [Code], [Note]) VALUES (12, 4, N'Fatih O.', N'I', 9, N'3-32', NULL)
SET IDENTITY_INSERT [dbo].[T_Employees] OFF

推荐答案

您可以使用递归CTE遍历层次结构

You can travers a hierarchy with a recursive CTE

这是经典的自上而下的CTE:

This is the classical top down CTE:

WITH EmployeesHierarchy AS
(
    SELECT ID,[Level],Employee,Department,Code,MasterId
    FROM T_Employees
    WHERE [Level]=1
    UNION ALL
    SELECT nextLevel.ID,nextLevel.[Level],nextLevel.Employee,nextLevel.Department,nextLevel.Code,nextLevel.MasterId
    FROM EmployeesHierarchy AS recCall
    INNER JOIN T_Employees AS nextLevel ON nextLevel.[Level]=recCall.[Level]+1 AND nextLevel.MasterId=recCall.ID
)
SELECT * FROM EmployeesHierarchy
ORDER BY [Level],MasterId
GO

现在反过来:我从项目中提到的员工开始,然后向上移动列表,直到不再有parentId为止.在CTE的第一部分中获得的项目数据将直接传递到所有行中.

And now the other way round: I start with the employees mentioned in the project and move up the list until there is no parentId any more. The Project's data gotten in the first part of the CTE are just passed through to show up in all rows.

WITH EmployeesHierarchy AS
(
    SELECT p.ID AS p_ID,p.ProjectId,e.ID AS e_ID,[Level],e.Employee,e.Department,e.Code,e.MasterId
    FROM T_Projects AS p 
        INNER JOIN T_Employees AS e ON p.EmployeeId=e.ID
    UNION ALL
    SELECT recCall.p_ID,recCall.ProjectId,nextLevel.ID,nextLevel.[Level],nextLevel.Employee,nextLevel.Department,nextLevel.Code,nextLevel.MasterId
    FROM EmployeesHierarchy AS recCall
    INNER JOIN T_Employees AS nextLevel ON nextLevel.ID=recCall.MasterId
)
SELECT * FROM EmployeesHierarchy
--WHERE ProjectId=456
ORDER BY [Level]

结果

+------+-----------+------+-------+------------+------------+------+----------+
| p_ID | ProjectId | e_ID | Level | Employee   | Department | Code | MasterId |
+------+-----------+------+-------+------------+------------+------+----------+
| 3    | 23        | 1    | 1     | Thomas S.  | A          | 1-4  | NULL     |
+------+-----------+------+-------+------------+------------+------+----------+
| 2    | 456       | 3    | 1     | Simone S.  | A          | 1-3  | NULL     |
+------+-----------+------+-------+------------+------------+------+----------+
| 1    | 456       | 1    | 1     | Thomas S.  | A          | 1-4  | NULL     |
+------+-----------+------+-------+------------+------------+------+----------+
| 2    | 456       | 6    | 2     | Loris P.   | B          | 2-15 | 3        |
+------+-----------+------+-------+------------+------------+------+----------+
| 1    | 456       | 4    | 2     | Stefan K.  | B          | 2-18 | 1        |
+------+-----------+------+-------+------------+------------+------+----------+
| 3    | 23        | 4    | 2     | Stefan K.  | B          | 2-18 | 1        |
+------+-----------+------+-------+------------+------------+------+----------+
| 3    | 23        | 7    | 3     | Lennon I.  | B          | 2-19 | 4        |
+------+-----------+------+-------+------------+------------+------+----------+
| 1    | 456       | 8    | 3     | Kerim K.   | C          | 2-66 | 4        |
+------+-----------+------+-------+------------+------------+------+----------+
| 2    | 456       | 9    | 3     | Ilmas Y.   | C          | 2-59 | 6        |
+------+-----------+------+-------+------------+------------+------+----------+
| 1    | 456       | 10   | 4     | Innes Y.   | D          | 3-89 | 8        |
+------+-----------+------+-------+------------+------------+------+----------+
| 2    | 456       | 12   | 4     | Fatih O.   | I          | 3-32 | 9        |
+------+-----------+------+-------+------------+------------+------+----------+
| 3    | 23        | 11   | 4     | Andreas U. | E          | 3-63 | 7        |
+------+-----------+------+-------+------------+------------+------+----------+

这篇关于如何从SQL表中检索层次结构数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆