我从来没有使用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
在这里,我张贴有关如何输出显示:
我只需要知道它是如何首先显示的经理,然后他的下属在一个循环。我想第一个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
的Q 1)是如何的N的值被递增得到?如果该值每次分配给N,则N值可以被递增1,但仅在第一次N值被初始化。
Q 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
我想,以显示这样的方式与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
这可能吗...?
我没有测试你的代码,只是试图帮助您了解如何在其工作意见;
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
递归CTE
我能想到的来说明其操作是最简单的例子;
;WITH Numbers AS
(
SELECT n = 1
UNION ALL
SELECT n + 1
FROM Numbers
WHERE n+1 <= 10
)
SELECT n
FROM Numbers
的Q 1)如何的N值是越来越增加。如果值是每次分配给N,则N值可以被递增1,但仅第一次N值是初始化。
A1:
在这种情况下,N
不是变量。 N
是一个别名。这是SELECT 1 AS N
的等价物。这是个人喜好的语法。有在一个CTE
混叠T-SQL
列的2点主要的方法。我已经包括在CTE
简单Excel
的模拟,试图说明所发生的事情更熟悉的方式。
-- Outside
;WITH CTE (MyColName) AS
(
SELECT 1
)
-- Inside
;WITH CTE AS
(
SELECT 1 AS MyColName
-- Or
SELECT MyColName = 1
-- Etc...
)
Q 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
SELECT ID,space(nLevel+
(CASE WHEN nLevel > 1 THEN nLevel ELSE 0 END)
)+Name
FROM Hierarchy
ORDER BY Family, nLevel
想简短的语义平行概述了已经正确答案。
在“简单”的术语中,递归CTE可以语义定义为以下部分:
1:CTE查询。也称为锚点。
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
说明:第一CTE查询返回基地的供应商(如叶子)谁不直接提供给任何其他供应商(-1)
在第一次迭代的递归查询得到所有谁提供给由锚返回的供应商的供应商。这个过程持续到条件返回元组。
UNION ALL返回所有在总递归调用的元组。
另一个很好的例子可以发现here。
PS:对于递归CTE工作,关系必须有一个层级(递归)条件上下工夫。例如:elementId = elementParentId ..你明白了吧。
执行过程是真的递归CTE混淆,我发现在https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx最好的答案和CTE执行过程的抽象是如下。
递归执行的语义如下:
--DROP TABLE #Employee
CREATE TABLE #Employee(EmpId BIGINT IDENTITY,EmpName VARCHAR(25),Designation VARCHAR(25),ManagerID BIGINT)
INSERT INTO #Employee VALUES('M11M','Manager',NULL)
INSERT INTO #Employee VALUES('P11P','Manager',NULL)
INSERT INTO #Employee VALUES('AA','Clerk',1)
INSERT INTO #Employee VALUES('AB','Assistant',1)
INSERT INTO #Employee VALUES('ZC','Supervisor',2)
INSERT INTO #Employee VALUES('ZD','Security',2)
SELECT * FROM #Employee (NOLOCK)
;
WITH Emp_CTE
AS
(
SELECT EmpId,EmpName,Designation, ManagerID
,CASE WHEN ManagerID IS NULL THEN EmpId ELSE ManagerID END ManagerID_N
FROM #Employee
)
select EmpId,EmpName,Designation, ManagerID
FROM Emp_CTE
order BY ManagerID_N, EmpId