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 

Я получаю ожидаемые результаты. Все шесть сотрудников из моей целевой таблицы возвращаются. Однако, если я переместил фильтр в cte вместо этого, я бросаю сотрудника (# 8).

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 

Теперь я понимаю, почему мои дополнительные ряды «Big Boss» попадались, когда я двигаюсь фильтр в КТР, но я с трудом оберточной мою голову вокруг, почему EmployeeID 8 отфильтровывается.

Любая помощь, помогающая мне обернуть мой простой разум вокруг этого поведения, очень ценится.

+0

Может # 8 был ребенком из отфильтрованный сотрудник? – usr

+0

D'oh! Вот и все. Спасибо!! –

ответ

2

Поскольку EmployeeId 6 не существует в tblTargetEmployees, поэтому, когда он попадает в рекурсию и начинает добавлять идентификатор сотрудника 6, он ищет, если он существует в таблице tblTargetEmployees. Это не так, что линия рекурсии останавливается, если и не получает идентификатор сотрудника 8.

Таким образом, чтобы использовать данные

  • 2 является BigBoss и представлен в таблице якорного
  • 6 является непосредственным начальником но не существует, поэтому после этого он не вызывает рекурсию.
  • 8 ожидает найти .....

переместить ИНЕКЕ 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 
Смежные вопросы