SQL 服务器递归 CTE - 为什么会出现这种行为?
SQL Server Recursive CTE - Why this behavior?
鉴于这些 tables...
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
我得到了预期的结果。我的目标 table 的所有六名员工都返回了。但是,如果我将过滤器移到 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
现在,我明白了为什么当我将过滤器移入 cte 时会出现额外的 "Big Boss" 行,但我很难理解为什么 employeeID 8 会被过滤掉。
非常感谢任何帮助我解决这种行为的简单想法。
因为 EmployeeId 6 在 tblTargetEmployees 中不存在,所以当它进入递归并开始添加员工 ID 6 时,它会查找它是否存在于 tblTargetEmployees table 中。如果永远不会到达员工 ID 8,那么递归行就不会停止。
所以要使用数据
- 2是bigboss,以anchor表示table
- 6是直属boss,但不存在所以之后不会再调用递归
- 8 正在等待被发现.....
将您的 WHERE 语句移到 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
)
SELECT *
FROM cte e
WHERE EXISTS (SELECT * FROM tblTargetEmployees te WHERE te.EmployeeID=e.EmployeeID)
ORDER by EmployeeID
鉴于这些 tables...
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
我得到了预期的结果。我的目标 table 的所有六名员工都返回了。但是,如果我将过滤器移到 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
现在,我明白了为什么当我将过滤器移入 cte 时会出现额外的 "Big Boss" 行,但我很难理解为什么 employeeID 8 会被过滤掉。
非常感谢任何帮助我解决这种行为的简单想法。
因为 EmployeeId 6 在 tblTargetEmployees 中不存在,所以当它进入递归并开始添加员工 ID 6 时,它会查找它是否存在于 tblTargetEmployees table 中。如果永远不会到达员工 ID 8,那么递归行就不会停止。
所以要使用数据
- 2是bigboss,以anchor表示table
- 6是直属boss,但不存在所以之后不会再调用递归
- 8 正在等待被发现.....
将您的 WHERE 语句移到 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
)
SELECT *
FROM cte e
WHERE EXISTS (SELECT * FROM tblTargetEmployees te WHERE te.EmployeeID=e.EmployeeID)
ORDER by EmployeeID