以递归方式检索服务中包含的用户

时间:2017-09-18 14:23:27

标签: sql sql-server

我有一个包含分层树的表,用于组织公司。

enter image description here

类型0:服务|输入1:用户

* Global Service
    * Logisticians
      > Mike
      > George
    * Technicians
      * Drivers
        > Stef
        > John
      * Controllers
        > Alfred

我需要检索给定服务的所有用户。

示例:

In: 0   Out: 5, 6, 7, 8, 9
In: 1   Out: 5, 6
In: 2   Out: 7, 8, 9
In: 3   Out: 7, 8
In: 4   Out: 9

如何使用参数(服务ID)查询我的表并将所有包含的用户作为结果?

输入:要查询的服务的ID

输出:此服务中包含的用户的ID

2 个答案:

答案 0 :(得分:0)

Frist创建一个数据类型来保存表

create type testTypeM as table (Id int , Name varchar(30), ParentId int, Type bit)

创建递归函数以获取层次结构

CREATE FUNCTION dbo.TestFuncM (@ServiceId int,  @TableSrc  testTypeM READONLY)
Returns @rtnTable table (Id int , Name varchar(30), ParentId int, Type bit)
BEGIN

insert @rtnTable
SELECT * from @TableSrc WHERE Parentid = @ServiceId

IF EXISTS (SELECT 1 FROM @rtnTable) 
BEGIN
    insert @rtnTable 
    SELECT B.* FROM @rtnTable A cross Apply dbo.TestFuncM( A.Id,@TableSrc) B

END 
return 
END 

将表格加载到表格数据类型

DECLARE @TableSrc  testTypeM 
Insert @TableSrc (Id,Name, ParentId, Type) Values
 (0, 'Global Service', NULL, 0)
,(1, 'Logisticians', 0 ,0)
,(2, 'Technicians', 0 ,0)
,(3, 'Drivers', 2, 0)
,(4, 'Controllers', 2, 0)
,(5, 'Mike', 1, 1)
,(6, 'George',1,1)
,(7, 'Stef', 3, 1)
,(8, 'John', 3, 1)
,(9, 'Alfred', 4, 1)


-- In Prosduction 
--INSERT @TableSrc  
--SELECT * FROM Your table 

以原样使用

SELECT * FROM dbo.TestFuncM(0, @TableSrc) WHERE TYPE = 1;

Id          Name                           ParentId    Type
----------- ------------------------------ ----------- -----
5           Mike                           1           1
6           George                         1           1
7           Stef                           3           1
8           John                           3           1
9           Alfred                         4           1

SELECT * FROM dbo.TestFuncM(1, @TableSrc) WHERE TYPE = 1;
Id          Name                           ParentId    Type
----------- ------------------------------ ----------- -----
5           Mike                           1           1
6           George                         1           1

SELECT * FROM dbo.TestFuncM(2, @TableSrc) WHERE TYPE = 1;
Id          Name                           ParentId    Type
----------- ------------------------------ ----------- -----
7           Stef                           3           1
8           John                           3           1
9           Alfred                         4           1

SELECT * FROM dbo.TestFuncM(3, @TableSrc) WHERE TYPE = 1;
Id          Name                           ParentId    Type
----------- ------------------------------ ----------- -----
7           Stef                           3           1
8           John                           3           1

SELECT * FROM dbo.TestFuncM(4, @TableSrc) WHERE TYPE = 1;
Id          Name                           ParentId    Type
----------- ------------------------------ ----------- -----
9           Alfred                         4           1

SELECT * FROM dbo.TestFuncM(5, @TableSrc) WHERE TYPE = 1;
-- No Result`enter code here`

答案 1 :(得分:0)

如果无法创建数据类型,请使用以下代码创建过程

结果是相同的

DECLARE @YourTable table (Id int , Name varchar(30), ParentId int, Type bit)


Insert @YourTable values  
 (0, 'Global Service', NULL, 0)
,(1, 'Logisticians', 0 ,0)
,(2, 'Technicians', 0 ,0)
,(3, 'Drivers', 2, 0)
,(4, 'Controllers', 2, 0)
,(5, 'Mike', 1, 1)
,(6, 'George',1,1)
,(7, 'Stef', 3, 1)
,(8, 'John', 3, 1)
,(9, 'Alfred', 4, 1)


-- CREATE PROCEDURE ProcedureName 
DECLARE @ServiceId int -- Procedure Paramter


DECLARE @ExistsNextLevel bit = 1 
DECLARE @TableResult table (Id int , Name varchar(30), ParentId int, Type bit)

--- Remove this line in procedure 
SET @ServiceId = 1

INSERT @TableResult SELECT * FROM @YourTable WHERE Parentid = @ServiceId

WHILE (@ExistsNextLevel = 1) 
BEGIN   

    SET @ExistsNextLevel = 0 
    IF EXISTS(SELECT 1 FROM @YourTable A WHERE EXISTS (SELECT 1 FROM @TableResult B WHERE A.Parentid = B.id)
    AND NOT EXISTS (SELECT 1 FROM @TableResult c Where A.id = C.id) ) 
    BEGIN 
        SET @ExistsNextLevel = 1
    END

    INSERT @TableResult
    SELECT * FROM @YourTable A WHERE EXISTS (SELECT 1 FROM @TableResult B WHERE A.Parentid = B.id)
    AND NOT EXISTS (SELECT 1 FROM @TableResult c Where A.id = C.id) 

END  


 SELECT * FROM @TableResult WHERE Type = 1
 -- GO

 -- EXEC ProcedureName  @ServiceId = 1