DBAtlas · Atlas de operaciones de bases de datos

CTE recursiva (WITH RECURSIVE)

Oracle

-- Hierarchy with CONNECT BY:
SELECT id, name, manager_id, LEVEL
FROM employee
START WITH manager_id IS NULL
CONNECT BY PRIOR id = manager_id;

-- Alternative (11gR2+): standard recursive WITH (the RECURSIVE keyword is not written)
WITH tree (id, name, manager_id) AS (
  SELECT id, name, manager_id FROM employee WHERE manager_id IS NULL
  UNION ALL
  SELECT c.id, c.name, c.manager_id
  FROM employee c JOIN tree a ON c.manager_id = a.id
)
SELECT * FROM tree;

Se usa para recorrer datos jerárquicos (árboles): organigramas, listas de materiales y similares. La forma clásica de Oracle es CONNECT BY / PRIOR y la pseudocolumna LEVEL; START WITH establece la fila raíz. Desde 11gR2 también se admite la CTE recursiva estándar.

PostgreSQL

WITH RECURSIVE tree (id, name, manager_id, level) AS (
  SELECT id, name, manager_id, 1
  FROM employee WHERE manager_id IS NULL
  UNION ALL
  SELECT c.id, c.name, c.manager_id, a.level + 1
  FROM employee c JOIN tree a ON c.manager_id = a.id
)
SELECT * FROM tree ORDER BY level;

WITH RECURSIVE combina una consulta ancla y una parte recursiva con UNION ALL; la parte recursiva se ejecuta repetidamente hasta que el resultado queda vacío. Ideal para jerarquías y recorridos de grafos. Protéjase de los bucles infinitos con UNION (en lugar de ALL) o con protección de ciclos.

MySQL

WITH RECURSIVE tree (id, name, manager_id, level) AS (
  SELECT id, name, manager_id, 1
  FROM employee WHERE manager_id IS NULL
  UNION ALL
  SELECT c.id, c.name, c.manager_id, a.level + 1
  FROM employee c JOIN tree a ON c.manager_id = a.id
)
SELECT * FROM tree ORDER BY level;

MySQL 8.0 (y MariaDB 10.2+) admiten la sintaxis WITH RECURSIVE conforme al estándar. La profundidad de recursión está limitada por la variable de sistema cte_max_recursion_depth (por defecto 1000). Las versiones anteriores requerían escribir un bucle en un procedimiento almacenado.

SQL Server

WITH tree (id, name, manager_id, level) AS (
  SELECT id, name, manager_id, 1
  FROM employee WHERE manager_id IS NULL
  UNION ALL
  SELECT c.id, c.name, c.manager_id, a.level + 1
  FROM employee c JOIN tree a ON c.manager_id = a.id
)
SELECT * FROM tree ORDER BY level
OPTION (MAXRECURSION 100);

En SQL Server no se escribe la palabra clave RECURSIVE para una CTE recursiva; una CTE con UNION ALL que se referencia a sí misma se trata automáticamente como recursiva. El límite de recursión por defecto es 100; cámbielo con OPTION (MAXRECURSION n) (0 = ilimitado, úselo con cuidado).

MongoDB

// Closest equivalent: the $graphLookup stage
db.employee.aggregate([
  { $match: { manager_id: null } },
  { $graphLookup: {
      from: "employee",
      startWith: "$id",
      connectFromField: "id",
      connectToField: "manager_id",
      as: "subordinates"
  } }
])

MongoDB no tiene CTE recursiva; para recorridos jerárquicos se usa la etapa de agregación $graphLookup. connectFromField/connectToField establecen los campos de enlace y maxDepth el límite de profundidad. Resuelve relaciones de árbol y de grafo en una sola consulta.

Redis

# Not applicable: Redis has no recursive queries.

Redis no ofrece un lenguaje de consulta. El recorrido de jerarquías/grafos se hace en el código de la aplicación o en el servidor con un script Lua; en Redis básico, el recorrido del árbol se escribe en el lado del cliente. (El soporte del módulo RedisGraph, usado anteriormente, terminó en 2023.)

Elasticsearch

# Not applicable: recursive queries are not supported.
# Approach: model with parent-child (join field) or nested,
# deep hierarchies are traversed on the application side.

Elasticsearch no ofrece consultas recursivas (no hay equivalente de WITH RECURSIVE / CONNECT BY). Las relaciones jerárquicas se modelan con el tipo de campo 'join' (parent/child) o almacenando la ruta del árbol (materialized path) en un campo; el recorrido de varios niveles suele hacerse en la aplicación.

Abrir en DBAtlas →