¿Cómo se obtiene el último registro generado en un CTE recursivo?
-
09-06-2019 - |
Pregunta
En el código siguiente, estoy usando un CTE (Expresión de tabla común) recursivo en SQL Server 2005 para intentar encontrar el nivel superior de una estructura jerárquica básica.La regla de esta jerarquía es que cada CustID tiene un ParentID y si el CustID no tiene padre, entonces ParentID = CustID y es el nivel más alto.
DECLARE @LookupID int
--Our test value
SET @LookupID = 1
WITH cteLevelOne (ParentID, CustID) AS
(
SELECT a.ParentID, a.CustID
FROM tblCustomer AS a
WHERE a.CustID = @LookupID
UNION ALL
SELECT a.ParentID, a.CustID
FROM tblCustomer AS a
INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID
WHERE c.CustID <> a.CustomerID
)
Entonces, si tblCustomer se ve así:
ParentID CustID
5 5
1 8
5 4
4 1
El resultado que obtengo del código anterior es:
ParentID CustID
4 1
5 4
5 5
Lo que quiero es sólo la última fila de ese resultado:
ParentID CustID
5 5
¿Cómo devuelvo el último registro generado en el CTE (que sería el CustID de nivel más alto)?
También tenga en cuenta que hay varias jerarquías de CustID no relacionadas en esta tabla, por lo que no puedo simplemente hacer SELECT * FROM tblCustomer WHERE ParentID = CustID.No puedo realizar pedidos por ParentID o CustID porque el número de identificación no está relacionado con su ubicación en la jerarquía.
Solución
Si solo desea obtener la profundidad de recursividad más alta, ¿no podría hacer algo como esto? Entonces, cuando realmente consulte el CTE, simplemente busque la fila con max (Profundidad).Al igual que:
DECLARE @LookupID int
--Our test value
SET @LookupID = 1;
WITH cteLevelOne (ParentID, CustID, Depth) AS
(
SELECT a.ParentID, a.CustID, 1
FROM tblCustomer AS a
WHERE a.CustID = @LookupID
UNION ALL
SELECT a.ParentID, a.CustID, c.Depth + 1
FROM tblCustomer AS a
INNER JOIN cteLevelOne AS c ON a.CustID = c.ParentID
WHERE c.CustID <> a.CustID
)
select * from CTELevelone where Depth = (select max(Depth) from CTELevelone)
o, adaptando lo que sugiere trevor, esto podría usarse con el mismo CTE:
select top 1 * from CTELevelone order by Depth desc
No creo que CustomerID fuera necesariamente lo que querías ordenar en el caso que describiste, pero tampoco tenía muy clara la pregunta.
Otros consejos
No estoy seguro de entender completamente el problema, pero para solucionarlo puedes intentar:
SELECT TOP 1 FROM cteLevelOne ORDER BY CustID DESC
Eso supone que el CustID también está en orden como en el ejemplo, y no algo así como un GUID.
Primero, el cte no finalizará si alguno de los padres e hijos es el mismo.Como es un CTE recursivo, debe finalizarse.Si el padre y el cliente son iguales, el ciclo no finalizará.
Msg 530, nivel 16, Estado 1, línea 15 La declaración terminó.La recursividad máxima 100 se agotó antes de completar la declaración.