Inicio > Cursos > SQL y Bases de Datos > CTEs con WITH
SQL y Bases de DatosConsultas AvanzadasLección 9 de 20

CTEs con WITH

Las CTEs (Common Table Expressions) son subconsultas con nombre definidas antes de la consulta principal usando WITH. Hacen el código más legible y permiten reutilizar resultados intermedios. Las CTEs recursivas son perfectas para datos jerárquicos como árboles de categorías.

-- CTE básica: más legible que subconsulta en FROM
WITH ventas_mensuales AS (
  SELECT
    DATE_TRUNC('month', fecha) AS mes,
    SUM(total) AS ingresos
  FROM orders
  WHERE fecha >= '2024-01-01'
  GROUP BY DATE_TRUNC('month', fecha)
)
SELECT
  mes,
  ingresos,
  LAG(ingresos) OVER (ORDER BY mes) AS mes_anterior,
  ROUND((ingresos - LAG(ingresos) OVER (ORDER BY mes)) * 100.0
        / LAG(ingresos) OVER (ORDER BY mes), 2) AS crecimiento_pct
FROM ventas_mensuales
ORDER BY mes;

-- Múltiples CTEs encadenadas
WITH
clientes_activos AS (
  SELECT DISTINCT user_id
  FROM orders
  WHERE fecha >= NOW() - INTERVAL '90 days'
),
resumen_clientes AS (
  SELECT
    u.id,
    u.nombre,
    COUNT(o.id) AS total_pedidos,
    SUM(o.total) AS gasto_total
  FROM users u
  JOIN orders o ON o.user_id = u.id
  WHERE u.id IN (SELECT user_id FROM clientes_activos)
  GROUP BY u.id, u.nombre
)
SELECT
  nombre,
  total_pedidos,
  gasto_total,
  ROUND(gasto_total / total_pedidos, 2) AS ticket_promedio
FROM resumen_clientes
ORDER BY gasto_total DESC
LIMIT 10;

-- CTE recursiva: árbol de categorías
-- Tabla: categorias(id, nombre, padre_id)
WITH RECURSIVE arbol_categorias AS (
  -- Caso base: categorías raíz (sin padre)
  SELECT id, nombre, padre_id, 0 AS nivel,
         nombre::TEXT AS ruta
  FROM categorias
  WHERE padre_id IS NULL

  UNION ALL

  -- Caso recursivo: hijos de cada categoría
  SELECT c.id, c.nombre, c.padre_id,
         ac.nivel + 1,
         ac.ruta || ' > ' || c.nombre
  FROM categorias c
  INNER JOIN arbol_categorias ac ON ac.id = c.padre_id
)
SELECT REPEAT('  ', nivel) || nombre AS categoria_indentada,
       ruta
FROM arbol_categorias
ORDER BY ruta;
ConsejoLas CTEs mejoran enormemente la legibilidad: puedes darle nombres descriptivos a los pasos intermedios de tu consulta. Sin embargo, en PostgreSQL cada CTE se evalúa una sola vez (fence de optimización). Si necesitas rendimiento máximo, compara con subconsultas.
← SubconsultasWindow Functions →

Practica esta lección

Resuelve los ejercicios del curso de SQL y Bases de Datos en la app, gratis y con corrección automática.

Empezar a practicar