Tho*_*mas 102 sql-server common-table-expression
我从不使用递归的CTE.我刚刚读了一篇关于它的文章.本文在Sql server CTE和递归的帮助下显示员工信息.它基本上显示了员工及其经理信息.我无法理解此查询的工作原理.这是查询:
WITH
cteReports (EmpID, FirstName, LastName, MgrID, EmpLevel)
AS
(
SELECT EmployeeID, FirstName, LastName, ManagerID, 1
FROM Employees
WHERE ManagerID IS NULL
UNION ALL
SELECT e.EmployeeID, e.FirstName, e.LastName, e.ManagerID,
r.EmpLevel + 1
FROM Employees e
INNER JOIN cteReports r
ON e.ManagerID = r.EmpID
)
SELECT
FirstName + ' ' + LastName AS FullName,
EmpLevel,
(SELECT FirstName + ' ' + LastName FROM Employees
WHERE EmployeeID = cteReports.MgrID) AS Manager
FROM cteReports
ORDER BY EmpLevel, MgrID
Run Code Online (Sandbox Code Playgroud)
这里我发布有关输出如何显示的信息:

我只需要知道它是如何首先显示管理器然后是循环中的下属.我想第一个sql语句只触发一次,并返回所有员工ID.
第二个查询重复触发,查询当前管理员ID所在的员工所在的数据库.
请解释sql语句如何在内部循环中执行,并告诉我sql执行顺序.谢谢.
;WITH Numbers AS
(
SELECT n = 1
UNION ALL
SELECT n + 1
FROM Numbers
WHERE n+1 <= 10
)
SELECT n
FROM Numbers
Run Code Online (Sandbox Code Playgroud)
问1)N的值如何增加?如果每次都将值赋值给N,那么N值可以递增,但只有第一次N值被初始化.
问2)CTE和员工关系的递归:
我添加两个经理并在第二个经理下添加更多员工的那一刻就是问题的开始.
我想显示第一个经理详细信息,而在下一行中只显示与该经理的下属相关的员工详细信息.
ID Name MgrID Level
--- ---- ------ -----
1 Keith NULL 1
2 Josh 1 2
3 Robin 1 2
4 Raja 2 3
5 Tridip NULL 1
6 Arijit 5 2
7 Amit 5 2
8 Dev 6 3
Run Code Online (Sandbox Code Playgroud)
我想用CTE表达式以这种方式显示结果.请告诉我在我的sql中修改了什么,以便拉动经理 - 员工关系.谢谢.
ID Name MgrID nLevel Family
----------- ------ ----------- ----------- --------------------
1 Keith NULL 1 1
3 Robin 1 2 1
2 Josh 1 2 1
4 Raja 2 3 1
5 Tridip NULL 1 2
7 Amit 5 2 2
6 Arijit 5 2 2
8 Dev 6 3 2
Run Code Online (Sandbox Code Playgroud)
这可能吗...?
Mar*_*rkD 203
我没有测试过您的代码,只是试图帮助您了解它在评论中的运作方式;
WITH
cteReports (EmpID, FirstName, LastName, MgrID, EmpLevel)
AS
(
-->>>>>>>>>>Block 1>>>>>>>>>>>>>>>>>
-- In a rCTE, this block is called an [Anchor]
-- The query finds all root nodes as described by WHERE ManagerID IS NULL
SELECT EmployeeID, FirstName, LastName, ManagerID, 1
FROM Employees
WHERE ManagerID IS NULL
-->>>>>>>>>>Block 1>>>>>>>>>>>>>>>>>
UNION ALL
-->>>>>>>>>>Block 2>>>>>>>>>>>>>>>>>
-- This is the recursive expression of the rCTE
-- On the first "execution" it will query data in [Employees],
-- relative to the [Anchor] above.
-- This will produce a resultset, we will call it R{1} and it is JOINed to [Employees]
-- as defined by the hierarchy
-- Subsequent "executions" of this block will reference R{n-1}
SELECT e.EmployeeID, e.FirstName, e.LastName, e.ManagerID,
r.EmpLevel + 1
FROM Employees e
INNER JOIN cteReports r
ON e.ManagerID = r.EmpID
-->>>>>>>>>>Block 2>>>>>>>>>>>>>>>>>
)
SELECT
FirstName + ' ' + LastName AS FullName,
EmpLevel,
(SELECT FirstName + ' ' + LastName FROM Employees
WHERE EmployeeID = cteReports.MgrID) AS Manager
FROM cteReports
ORDER BY EmpLevel, MgrID
Run Code Online (Sandbox Code Playgroud)
CTE我可以想到一个递归的最简单的例子来说明它的操作是;
;WITH Numbers AS
(
SELECT n = 1
UNION ALL
SELECT n + 1
FROM Numbers
WHERE n+1 <= 10
)
SELECT n
FROM Numbers
Run Code Online (Sandbox Code Playgroud)
问1)N的值如何增加.如果每次都将值赋值给N,那么N值可以递增,但只有第一次N值被初始化.
A1:在这种情况下,N不是变量.N是别名.它相当于SELECT 1 AS N.这是个人偏好的语法.有在混叠列的2种主要的方法CTE中T-SQL.我已经包含了简单的模拟CTE中Excel尝试和所发生的事情更熟悉的方式说明.
-- Outside
;WITH CTE (MyColName) AS
(
SELECT 1
)
-- Inside
;WITH CTE AS
(
SELECT 1 AS MyColName
-- Or
SELECT MyColName = 1
-- Etc...
)
Run Code Online (Sandbox Code Playgroud)

问2)现在这里关于CTE和员工关系的递归我添加两个经理并在第二个经理下添加更多员工然后问题开始的那一刻.我想显示第一个经理详细信息,在接下来的行中,只有那些员工的详细信息将来自该经理的下属
A2:
这段代码是否回答了你的问题?
--------------------------------------------
-- Synthesise table with non-recursive CTE
--------------------------------------------
;WITH Employee (ID, Name, MgrID) AS
(
SELECT 1, 'Keith', NULL UNION ALL
SELECT 2, 'Josh', 1 UNION ALL
SELECT 3, 'Robin', 1 UNION ALL
SELECT 4, 'Raja', 2 UNION ALL
SELECT 5, 'Tridip', NULL UNION ALL
SELECT 6, 'Arijit', 5 UNION ALL
SELECT 7, 'Amit', 5 UNION ALL
SELECT 8, 'Dev', 6
)
--------------------------------------------
-- Recursive CTE - Chained to the above CTE
--------------------------------------------
,Hierarchy AS
(
-- Anchor
SELECT ID
,Name
,MgrID
,nLevel = 1
,Family = ROW_NUMBER() OVER (ORDER BY Name)
FROM Employee
WHERE MgrID IS NULL
UNION ALL
-- Recursive query
SELECT E.ID
,E.Name
,E.MgrID
,H.nLevel+1
,Family
FROM Employee E
JOIN Hierarchy H ON E.MgrID = H.ID
)
SELECT *
FROM Hierarchy
ORDER BY Family, nLevel
Run Code Online (Sandbox Code Playgroud)
SELECT ID,space(nLevel+
(CASE WHEN nLevel > 1 THEN nLevel ELSE 0 END)
)+Name
FROM Hierarchy
ORDER BY Family, nLevel
Run Code Online (Sandbox Code Playgroud)
想概述一个与已经正确的答案平行的简短语义.
在"简单"术语中,递归CTE可以在语义上定义为以下部分:
1:CTE查询.也称为ANCHOR.
2:在(1)中使用UNION ALL(或UNION或EXCEPT或INTERSECT)对CTE进行递归CTE查询,从而返回最终结果.
3:角落/终止条件.默认情况下,递归查询返回的行/元组不再存在.
一个简短的例子,可以使图片清晰:
;WITH SupplierChain_CTE(supplier_id, supplier_name, supplies_to, level)
AS
(
SELECT S.supplier_id, S.supplier_name, S.supplies_to, 0 as level
FROM Supplier S
WHERE supplies_to = -1 -- Return the roots where a supplier supplies to no other supplier directly
UNION ALL
-- The recursive CTE query on the SupplierChain_CTE
SELECT S.supplier_id, S.supplier_name, S.supplies_to, level + 1
FROM Supplier S
INNER JOIN SupplierChain_CTE SC
ON S.supplies_to = SC.supplier_id
)
-- Use the CTE to get all suppliers in a supply chain with levels
SELECT * FROM SupplierChain_CTE
Run Code Online (Sandbox Code Playgroud)
说明:第一个CTE查询返回不直接提供给任何其他供应商的基础供应商(如叶子)(-1)
第一次迭代中的递归查询获得供应给ANCHOR返回的供应商的所有供应商.这个过程一直持续到条件返回元组.
UNION ALL在总递归调用中返回所有元组.
另一个很好的例子可以在这里找到.
PS:要使递归CTE起作用,关系必须具有分层(递归)条件才能工作.例如:elementId = elementParentId ..你明白了.
小智 7
执行过程真的与递归CTE混淆,我在https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx和CTE执行过程的摘要中找到了最佳答案如下.
递归执行的语义如下:
| 归档时间: |
|
| 查看次数: |
170996 次 |
| 最近记录: |