web-dev-qa-db-ja.com

SQL Server CTE下から上への再帰的なWhere句

EmployeeId、ManagerId、およびNameフィールドを持つEmployeeテーブルがあります。

目標は、従業員からトップマネージャーにすべての行をフェッチして再帰的にすることです(ManagerIdはnull)。

私はこのリンクを見つけました これはコードのベースを取得するのに役立ちましたが、私の場合にはうまくいきません

DECLARE @EmployeeTable table ([EmployeeId] int, [name] varchar(10), [managerId] int)
INSERT @EmployeeTable VALUES (1,'Jerome', NULL )  -- tree is as follows:
INSERT @EmployeeTable VALUES (2,'Joe'   ,1)     --                      1-Jerome
INSERT @EmployeeTable VALUES (3,'Paul'  ,2)     --                     /        \
INSERT @EmployeeTable VALUES (4,'Jack'  ,3)     --              2-Joe               9-Bill
INSERT @EmployeeTable VALUES (5,'Daniel',3)     --            /       \                  \
INSERT @EmployeeTable VALUES (6,'David' ,2)     --     3-Paul          6-David       10-Sam
INSERT @EmployeeTable VALUES (7,'Ian'   ,6)     --    /      \            /    \
INSERT @EmployeeTable VALUES (8,'Helen' ,6)     -- 4-Jack  5-Daniel   7-Ian    8-Helen
INSERT @EmployeeTable VALUES (9,'Bill ' ,1)     --
INSERT @EmployeeTable VALUES (10,'Sam'  ,9)     --

DECLARE @employeeId int = 3

;WITH StaffTree AS
(
    SELECT 
        c.[EmployeeId], c.[name], c.managerId, 0 AS [Level]
        FROM @EmployeeTable c
        LEFT OUTER JOIN @EmployeeTable  cc ON c.managerId=cc.EmployeeId
        WHERE c.EmployeeId=@employeeId OR (@employeeId IS NULL AND     c.managerId IS NULL)
    UNION ALL
        SELECT 
            s.[EmployeeId], s.[name], s.managerId, t.[Level]+1
        FROM StaffTree t
            INNER JOIN @EmployeeTable s ON t.[EmployeeId]=s.managerId
        WHERE s.managerId=@employeeId OR @employeeId IS NULL OR t.Level>1
)
SELECT * FROM StaffTree

従業員3の階層を選択した場合、結果は次のようになります。

EmployeeId | Name    | ManagerId 
1          | Jerome  | NULL
2          | Joe     | 1
3          | Paul    | 2
3
Lenny32

再帰部分の内部結合の列を交換することは、これを回避する方法です。

結合列がt.[EmployeeId]=s.managerIdからs.[EmployeeId]=t.managerIdに変更されました

必要と思われない部分を削除しました。

DECLARE @employeeId int = 3

;WITH StaffTree AS
(
    SELECT 
        c.[EmployeeId], c.[name], c.managerId, 0 AS [Level]
        FROM @EmployeeTable c
        WHERE c.EmployeeId=@employeeId OR (@employeeId IS NULL AND     c.managerId IS NULL)
    UNION ALL
        SELECT 
            s.[EmployeeId], s.[name], s.managerId, t.[Level]+1
        FROM StaffTree t
        INNER JOIN @EmployeeTable s ON s.[EmployeeId]=t.managerId
)
SELECT EmployeeId,
       name,
       managerId 
FROM StaffTree
ORDER BY managerId asc;

結果

EmployeeId  name    managerId
1           Jerome  NULL
2           Joe     1
3           Paul    2
2
Randi Vertongen

リンクした例をコピーするときに小さなエラーが発生したようです-

c.[EmployeeId], c.[name], c.managerId, 0 AS [Level]

する必要があります

c.[EmployeeId], c.[name], c.managerId, 1 AS [Level]

変更を加えると、コードは例と同じように機能します。

0
Darren G

このリンクは、優れた有用な例で再帰CTEを学習するのに役立ちます。 https://www.codeproject.com/Articles/818694/SQL-queries-to-manage-hierarchical-or-parent-child

0
Pantea Tourang