CTE's Recursivas

09/10/2009 - 03:46 por alex | Informe spam
Hola , tengo una duda con respecto a las CTE's recursivas. El ejemplo que
sale en books online al ejecutarlo los resultados comienzan ordenados por la
columna LEVEL de menor a mayor 0 1 2 3 4 pero en cierto punto comienza a
descender como 0 1 2 3 4 3 3 2, o sea no estan ordenados de menor a mayor
todo el tiempo que es como se supone que trabaja haciendo UNION ALL a todos
los resultados parciales. Alguien me puede ayudar a comprender esto?
El ejemplo de books online (el ultimo WHERE lo elimine para que salgan todos
los resultados:

USE AdventureWorks;
GO
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS
(
SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
0 AS Level
FROM HumanResources.Employee AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.EmployeeID AND edh.EndDate IS NULL
WHERE ManagerID IS NULL
UNION ALL
SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
Level + 1
FROM HumanResources.Employee AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.EmployeeID AND edh.EndDate IS NULL
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, Title, Level
FROM DirectReports
 

Leer las respuestas

#1 Carlos M. Calvelo
09/10/2009 - 13:40 | Informe spam
Hola alex,

On 9 okt, 03:46, "alex" wrote:
Hola , tengo una duda con respecto a las CTE's recursivas. El ejemplo que
sale en books online al ejecutarlo los resultados comienzan ordenados por la
columna LEVEL de menor a mayor 0 1 2 3 4 pero en cierto punto comienza a
descender como 0 1 2 3 4 3 3 2, o sea no estan ordenados de menor a mayor
todo el tiempo que es como se supone que trabaja haciendo UNION ALL a todos
los resultados parciales. Alguien me puede ayudar a comprender esto?
El ejemplo de books online (el ultimo WHERE lo elimine para que salgan todos
los resultados:

USE AdventureWorks;
GO
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS
(
SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
0 AS Level
FROM HumanResources.Employee AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.EmployeeID AND edh.EndDate IS NULL
WHERE ManagerID IS NULL
UNION ALL
SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
Level + 1
FROM HumanResources.Employee AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.EmployeeID AND edh.EndDate IS NULL
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, Title, Level
FROM DirectReports



El "como se supone que trabaja" para entender o explicar QUE
significa una operación y el "como lo hace realmente" son cosas
distintas. Lo importante es que el resultado sea el mismo para
como nosotros lo explicamos y para como se ejecuta realmente.
Todas las posibles ordenaciones del resultado son el mismo
resultado. O sea que el "QUE hace" es lo mismo aunque el "COMO"
pueda ser distinto.

En todo caso el "como lo hace" tiene que ver con la ejecución
recursiva del CTE.
Mira este ejemplo. Fíjate en el patrón que sigue la enumeración
en la columa 'nombre' y el orden en se presentan los ParentID con
respecto a los IDŽs que ya estaban en el resultado.
Después nos cuentas que patrón descubres y que deduces de eso en
cuanto a "como" lo hace.


declare @T table(ID int, ParentID int, Nombre varchar(20))
;
insert into @T (ID, ParentID, Nombre)
select 1, null, 'Director 1'
union select 2, null, 'Director 2'
union select 3, 1, 'Jefe 1/1'
union select 4, 1, 'Jefe 1/2'
union select 5, 2, 'Jefe 2/1'
union select 6, 2, 'Jefe 2/2'
union select 7, 3, 'Pepito 1/1/1'
union select 8, 3, 'Pepito 1/1/2'
union select 9, 4, 'Pepito 1/2/1'
union select 10, 4, 'Pepito 1/2/2'
union select 11, 5, 'Pepito 2/1/1'
union select 12, 5, 'Pepito 2/1/2'
union select 13, 6, 'Pepito 2/2/1'
union select 14, 6, 'Pepito 2/2/2'
;
with A as
(
select ParentID, ID, Nombre, 1 as Nivel
from @T
where ParentID is null
union all
select T.ParentID, T.ID, T.Nombre, A.Nivel + 1
from @T T join A on T.ParentID = A.ID
)
select * from A
;


Saludos,
Carlos

Preguntas similares