2016-07-08 5 views
2
これらのテーブルを考えると

...SQL Server再帰CTE - この動作はなぜですか?

CREATE TABLE tblEmployees (
    EmployeeID SMALLINT, 
    ReportsTo SMALLINT, 
    IsBigBoss BIT); 

CREATE TABLE tblTargetEmployees (
    EmployeeID SMALLINT); 

INSERT INTO tblEmployees VALUES 
(1,NULL,NULL), 
(2,1,1), 
(3,1,1), 
(4,1,1), 
(5,1,1), 
(6,2,0), 
(7,6,0), 
(8,6,0), 
(9,3,0), 
(10,4,0), 
(11,10,0), 
(12,10,0), 
(13,5,0), 
(14,2,0), 
(15,10,0); 

INSERT INTO tblTargetEmployees VALUES 
(8), 
(9), 
(10), 
(11), 
(12), 
(14); 

そして、このクエリ...

WITH cte AS (
    SELECT e.EmployeeID, BigBossID=e.EmployeeID, e.ReportsTo 
     FROM tblEmployees e 
     WHERE e.IsBigBoss=1 

    UNION all 

    SELECT e.EmployeeID, cte.BigBossID, e.ReportsTo 
     FROM tblEmployees e 
      JOIN cte ON e.ReportsTo=cte.EmployeeID 
) 

SELECT * 
    FROM cte 
    WHERE EXISTS (SELECT * FROM tblTargetEmployees te WHERE te.EmployeeID=cte.EmployeeID) 
    ORDER by EmployeeID 

は私が期待される結果を得ます。ターゲットテーブルの6人の従業員全員が返されます。しかし、代わりにフィルタをcteに移動すると、私は従業員を落とします(#8)。私はCTEにフィルタを移動すると、私余分な「ビッグボス」の行が渡って来る理由

WITH cte AS (
    SELECT e.EmployeeID, BigBossID=e.EmployeeID, e.ReportsTo 
     FROM tblEmployees e 
     WHERE e.IsBigBoss=1 

    UNION all 

    SELECT e.EmployeeID, cte.BigBossID, e.ReportsTo 
     FROM tblEmployees e 
      JOIN cte ON e.ReportsTo=cte.EmployeeID 
     WHERE EXISTS (SELECT * FROM tblTargetEmployees te WHERE te.EmployeeID=e.EmployeeID) 
) 

SELECT * 
    FROM cte 
    ORDER by EmployeeID 

は今、私は理解しますが、私は社員コード8が除外されますなぜまわりで私の頭をラップに苦労しています。

私はこの行動のまわりで私の簡単な心を包み込むのを手伝ってくれて助けてくれて大変感謝しています。

+0

を望むでしょう.....見つけられるのを待っていますフィルタリングされた従業員 – usr

+0

D'oh!それでおしまい。ありがとうございました!! –

答えて

2

EmployeeId 6はtblTargetEmployeesに存在しないため、再帰に達して従業員ID 6の追加を開始すると、tblTargetEmployeesテーブルに存在するかどうかを調べます。再帰のその行があれば停止し、8

ので

  • 6が直接の上司である

    • 2はbigbossで、アンカーテーブルで表現されたデータを使用する従業員IDを取得することはありませんので、それはしていません存在しないので、それ以降は再帰を呼び出さない。 はたぶん、#8の子だった
    CTEのあなたのWHEREステートメントoutsdeを移動

    、あなたは結果があなたが

    ;WITH cte AS (
        SELECT e.EmployeeID, BigBossID=e.EmployeeID, e.ReportsTo 
         FROM tblEmployees e 
         WHERE e.IsBigBoss=1 
    
        UNION all 
    
        SELECT e.EmployeeID, cte.BigBossID, e.ReportsTo 
         FROM tblEmployees e 
          JOIN cte ON e.ReportsTo=cte.EmployeeID 
    ) 
    
    SELECT * 
        FROM cte e 
        WHERE EXISTS (SELECT * FROM tblTargetEmployees te WHERE te.EmployeeID=e.EmployeeID) 
        ORDER by EmployeeID 
    
  • 関連する問題