2012-02-03 32 views
10

Considere el siguiente¿Por qué no podemos usar uniones externas en CTE recursivo?

;WITH GetParentOfChild AS 
    (
     SELECT 
      Rn = ROW_NUMBER() Over(Order By (Select 1)) 
      ,row_id AS Parents 
      ,parent_account_id As ParentId 
     FROM siebelextract..account 
     WHERE row_id = @ChildId 
     UNION ALL 
     SELECT 
      Rn + 1 
      ,a.row_id as Parents 
      ,a.parent_account_id As ParentId  
     FROM siebelextract..account a 
     JOIN GetParentOfChild gp on a.row_id = gp.ParentId 
    ) 

SELECT TOP 1 @ChildId = Parents 
FROM GetParentOfChild 
ORDER BY Rn DESC 

Lo que sí es que dada cualquier niño, devolverá el padre nivel de la raíz .... El programa está perfectamente funcionando bien todo el tiempo ...

Justo fuera por curiosidad aras experimental/i cambiado la UNIRSE a izquierda combinación externa e informó

Msg 462, nivel 16, estado 1, procedimiento GetParent, línea 9 combinación externa no está permitido en la parte recursiva de una mesa común recursiva expresión 'GetParentOfChild'.

Mi pregunta es por qué la parte recursiva de CTE no puede aceptar la unión externa izquierda? ¿Es por diseño?

Gracias

Respuesta

6

Sí, es por diseño, leer Guidelines for Defining and Using Recursive Common Table Expressions

Los siguientes elementos se no admitidas en el CTE_query_definition de un miembro recursivo :

  • SELECT DISTINCT
  • GRUPO POR
  • TIENE
  • agregación escalar
  • TOP
  • IZQUIERDA, DERECHA, OUTER JOIN (interior está permitido Unir)
  • subconsultas

Tenga en cuenta que si su consulta gire a la izquierda unirse a ella auto a través de CTE puede convertirse en una recursión infinita.

+8

No creo que esta respuesta o el enlace realmente responda "por qué". Quería unir dos uniones a la izquierda (a tablas externas) para controlar la dirección de la siguiente iteración, por ejemplo. La recursividad infinita no parece una buena razón para abandonar todos los bucles while. – crokusek

+3

@crokusek, prepare su consulta de coalescencia en una expresión de cte anterior y únela en su consulta de cte recursiva. – danihp

+0

Ha, lo probé y funciona, buen truco. Si lo hice bien, tuve que convertir las uniones izquierdas en totalmente exteriores en el cte. Se ejecutó pero el plan de consulta se vuelve miserable: calcula completamente el exterior antes de comenzar en el rte (no terminaría, dependiendo de los tamaños), perdiendo la bondad de sondear recursivamente solo exactamente lo que necesitaba. Un cursor funcionaría mejor excepto cuando el resultado de cte es pequeño. Probablemente una buena solución para algunos casos, no obstante. – crokusek

8

No puede usar LEFT JOIN con CTE recursivo pero puede usar APLICACIÓN EXTERNA que debería dar los mismos resultados.

Cuestiones relacionadas