- 1 1. Introducción
- 2 2. Conceptos básicos de la cláusula WITH (Expresiones de tabla comunes)
- 3 3. Uso básico de la cláusula WITH de MySQL
- 4 4. Practical Examples of Recursive WITH Clauses
- 5 5. Notas y consideraciones al usar la cláusula WITH
- 6 6. Casos de uso prácticos en escenarios del mundo real
- 7 7. Preguntas frecuentes (FAQ)
- 7.1 Q1: ¿Cuándo debería usar la cláusula WITH?
- 7.2 Q2: ¿Cuándo es útil un CTE recursivo?
- 7.3 Q3: ¿Las consultas que usan la cláusula WITH son más eficientes que las vistas?
- 7.4 Q4: ¿Qué causa la degradación del rendimiento al usar la cláusula WITH?
- 7.5 Q5: ¿Qué alternativas existen para versiones de MySQL que no soportan la cláusula WITH?
- 7.6 Q6: ¿Cuáles son las mejores prácticas al usar la cláusula WITH?
- 8 8. Conclusión
1. Introducción
MySQL es un sistema de gestión de bases de datos ampliamente usado por desarrolladores y administradores de bases de datos, que ofrece una funcionalidad SQL potente y flexible. Entre sus características, la cláusula WITH (Expresión de Tabla Común: CTE), introducida en MySQL 8.0, es una herramienta poderosa que hace que las consultas SQL sean más legibles y mejora su mantenibilidad.
Este artículo explica la cláusula WITH desde lo básico hasta usos avanzados, dirigido a usuarios principiantes e intermedios. En particular, cubrimos temas prácticos como reemplazar subconsultas y implementar consultas recursivas.
Para quienes están aprendiendo SQL o tienen dificultades para optimizar consultas en su trabajo diario, este artículo pretende ofrecer soluciones concretas. Siga el contenido a continuación para comprender los fundamentos de la cláusula WITH y aplicarlos en escenarios del mundo real.
2. Conceptos básicos de la cláusula WITH (Expresiones de tabla comunes)
¿Qué es la cláusula WITH?
La cláusula WITH es una sintaxis utilizada para definir un conjunto de resultados temporal (Expresión de Tabla Común, CTE) dentro de una consulta SQL y referenciarlo en consultas posteriores. Disponible a partir de MySQL 8.0, permite reescribir subconsultas complejas de forma más clara y concisa.
Por ejemplo, al escribir subconsultas directamente, la legibilidad puede disminuir y la consulta completa puede volverse extensa. Al usar la cláusula WITH, se pueden dividir las consultas en bloques lógicos, facilitando su comprensión.
Sintaxis básica de la cláusula WITH
A continuación se muestra la sintaxis básica de la cláusula WITH:
WITH table_name AS (
SELECT column1, column2
FROM original_table
WHERE condition
)
SELECT column1, column2
FROM table_name;
En esta sintaxis, se define una tabla virtual (Expresión de Tabla Común) después de WITH, y luego se utiliza en la consulta principal. Esto hace que las subconsultas usadas repetidamente sean más fáciles de expresar de forma concisa.
Diferencias con subconsultas y vistas
La cláusula WITH crea un conjunto de resultados disponible temporalmente y difiere de las subconsultas y vistas en varios aspectos.
| Feature | WITH Clause | Subquery | View |
|---|---|---|---|
| Scope | Valid only within the query | Usable only where defined | Reusable across the entire database |
| Persistence | Temporary | Temporary | Permanent |
| Purpose | Simplifies complex queries | Temporary data extraction | Frequently reused data extraction |
La cláusula WITH es más legible que las subconsultas y es ideal cuando no se necesita crear un objeto permanente como una vista.
Ventajas de usar la cláusula WITH
- Mejora de la legibilidad de la consulta Incluso cuando existen múltiples subconsultas, organizarlas con la cláusula WITH clarifica la estructura.
- Mejora de la reutilización Al definir un conjunto de resultados temporal, puede ser referenciado varias veces dentro de la consulta.
- Mejora del mantenimiento Como las consultas pueden dividirse lógicamente, las modificaciones y extensiones resultan más sencillas.
3. Uso básico de la cláusula WITH de MySQL
Reemplazo de subconsultas
La cláusula WITH es una herramienta poderosa para simplificar subconsultas complejas. Incrustar subconsultas directamente puede complicar toda la consulta y dificultar su lectura, pero usar la cláusula WITH mejora la legibilidad.
A continuación se muestra un ejemplo básico de reemplazo de una subconsulta mediante la cláusula WITH.
Usando una subconsulta:
SELECT AVG(sales.total) AS average_sales
FROM (
SELECT SUM(amount) AS total
FROM orders
GROUP BY customer_id
) AS sales;
Usando la cláusula WITH:
WITH sales AS (
SELECT SUM(amount) AS total
FROM orders
GROUP BY customer_id
)
SELECT AVG(sales.total) AS average_sales
FROM sales;
En este ejemplo, se define un conjunto de resultados temporal llamado sales mediante la cláusula WITH y luego se referencia en la consulta principal. Esto hace que toda la consulta sea más fácil de entender y esté mejor organizada.
Definición de múltiples Expresiones de Tabla Común (CTE)
La cláusula WITH permite definir múltiples CTE. Esto posibilita una mayor modularización de consultas complejas.
Ejemplo:
WITH
sales_per_customer AS (
SELECT customer_id, SUM(amount) AS total_sales
FROM orders
GROUP BY customer_id
),
high_value_customers AS (
SELECT customer_id
FROM sales_per_customer
WHERE total_sales > 10000
)
SELECT customer_id
FROM high_value_customers;
En este ejemplo, sales_per_customer calcula el total de ventas por cliente, y con base en ese resultado, high_value_customers extrae los clientes con altos montos de compra. Al usar múltiples CTEs de forma secuencial, las consultas pueden construirse paso a paso.
Using Nested CTEs
Al usar CTEs anidados, puedes realizar operaciones de datos más complejas.
Example:
WITH
sales_data AS (
SELECT product_id, SUM(amount) AS total_sales
FROM orders
GROUP BY product_id
),
ranked_sales AS (
SELECT product_id, total_sales,
RANK() OVER (ORDER BY total_sales DESC) AS rank
FROM sales_data
)
SELECT product_id, total_sales
FROM ranked_sales
WHERE rank <= 5;
En esta consulta, sales_data agrega las ventas por producto, y ranked_sales asigna rangos basados en el volumen de ventas. Finalmente, se extraen los cinco productos principales.
Key Points for Practical Usage
- Think in Logical Steps Construye CTEs paso a paso para mejorar la legibilidad y facilitar la depuración.
- Store Intermediate Calculation Results Agrupa los resultados de cálculos o condiciones de filtrado usadas múltiples veces en CTEs para reducir la duplicación de código.
- Be Careful with Large Datasets Dado que los CTEs generan conjuntos de resultados temporales, considera el impacto en el rendimiento al trabajar con grandes volúmenes de datos.
4. Practical Examples of Recursive WITH Clauses
What Is a Recursive WITH Clause?
Una cláusula WITH recursiva (CTE recursivo) es un método que utiliza una Expresión de Tabla Común para ejecutar repetidamente una consulta autorreferenciada, lo que permite procesar datos jerárquicos y cálculos iterativos. Los CTEs recursivos son compatibles con MySQL 8.0 y versiones posteriores y son especialmente útiles al trabajar con relaciones padre‑hijo y estructuras jerárquicas.
Basic Syntax of a Recursive CTE
Para definir un CTE recursivo, usa la palabra clave WITH RECURSIVE. La sintaxis básica es la siguiente:
WITH RECURSIVE recursive_table_name AS (
initial_query -- starting point of the recursion
UNION ALL
recursive_query -- query called recursively
)
SELECT * FROM recursive_table_name;
- Initial query : Recupera el primer conjunto de datos para el proceso recursivo.
- Recursive query : Genera nuevas filas basándose en la consulta inicial o en los resultados de la iteración anterior.
- UNION ALL : Combina los resultados de la consulta inicial y la consulta recursiva.
Example: Processing Hierarchical Data
Los CTEs recursivos se usan a menudo para expandir datos con una estructura jerárquica (p. ej., árboles organizacionales o árboles de categorías).
Example: Expanding an employee management hierarchy
Considera la siguiente tabla employees:
| employee_id | name | manager_id |
|---|---|---|
| 1 | Alice | NULL |
| 2 | Bob | 1 |
| 3 | Charlie | 1 |
| 4 | David | 2 |
Con estos datos, podemos crear una consulta que recupere la jerarquía completa a partir de un empleado dado.
WITH RECURSIVE employee_hierarchy AS (
-- Initial query: get top-level employees
SELECT employee_id, name, manager_id, 1 AS level
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Recursive query: get direct reports
SELECT e.employee_id, e.name, e.manager_id, eh.level + 1
FROM employees e
INNER JOIN employee_hierarchy eh
ON e.manager_id = eh.employee_id
)
SELECT * FROM employee_hierarchy;
Result:
| employee_id | name | manager_id | level |
|---|---|---|---|
| 1 | Alice | NULL | 1 |
| 2 | Bob | 1 | 2 |
| 3 | Charlie | 1 | 2 |
| 4 | David | 2 | 3 |
En esta consulta, los subordinados se buscan de forma recursiva basándose en manager_id, expandiendo la jerarquía completa.
Limitations and Cautions for Recursive CTEs
- An End Condition Is Required Si la consulta recursiva no cumple una condición de finalización, puede producirse un bucle infinito. Siempre incluye condiciones apropiadas para evitar recursiones infinitas.
- Performance Impact Los CTEs recursivos pueden implicar muchos cálculos sobre conjuntos de datos grandes, lo que puede aumentar el tiempo de ejecución. Usa cláusulas
LIMITy condiciones de filtrado para mejorar la eficiencia. - Recursion Depth Limits MySQL tiene un límite en la profundidad de recursión, así que ten cuidado al ejecutar procesos recursivos muy profundos. Este límite se puede configurar con el parámetro
max_recursive_iterations.
Escenarios donde los CTE recursivos son útiles
- Recorrer estructuras de carpetas : Buscar recursivamente carpetas y subcarpetas.
- Crear organigramas : Visualizar jerarquías de gerentes a subordinados.
- Mostrar árboles de categorías : Recuperar categorías de productos jerárquicas o estructuras de etiquetas.
Los CTE recursivos son una forma poderosa de escribir consultas SQL concisas para estos escenarios, al tiempo que mejoran la legibilidad.
5. Notas y consideraciones al usar la cláusula WITH
Impacto en el rendimiento y optimización
- Recalculación del CTE En general, un CTE definido con la cláusula WITH se recalcula cada vez que se hace referencia a él. Por lo tanto, usar el mismo CTE varias veces puede aumentar el tiempo de ejecución de la consulta. Ejemplo:
WITH sales AS ( SELECT product_id, SUM(amount) AS total_sales FROM orders GROUP BY product_id ) SELECT * FROM sales WHERE total_sales > 1000; SELECT COUNT(*) FROM sales;
En el caso anterior, sales se referencia dos veces, por lo que se calcula dos veces. Para evitar esto, cuando necesites referenciar los resultados múltiples veces, almacenar el resultado en una tabla temporal puede ser eficaz.
Solución:
CREATE TEMPORARY TABLE temp_sales AS
SELECT product_id, SUM(amount) AS total_sales
FROM orders
GROUP BY product_id;
SELECT * FROM temp_sales WHERE total_sales > 1000;
SELECT COUNT(*) FROM temp_sales;
- Dividir CTEs complejos Si la cláusula WITH se vuelve demasiado anidada, la consulta completa puede volverse compleja y más difícil de depurar. Es importante dividir la lógica adecuadamente para que el procesamiento dentro de un solo CTE no se vuelva excesivamente complicado.
Uso de cláusulas WITH en conjuntos de datos grandes
La cláusula WITH genera conjuntos de datos temporales durante la ejecución. Al manejar grandes volúmenes de datos, esto puede suponer una carga para la memoria o el almacenamiento.
Contramedidas:
- Filtrar datos con cláusulas WHERE Reducir el cómputo filtrando datos innecesarios dentro del CTE.
WITH filtered_orders AS ( SELECT * FROM orders WHERE order_date > '2023-01-01' ) SELECT customer_id, SUM(amount) FROM filtered_orders GROUP BY customer_id;
- Usar cláusulas LIMIT Si el conjunto de datos es grande, usa
LIMITpara extraer solo los datos que necesitas.
Compatibilidad de versiones de MySQL
La cláusula WITH en MySQL es compatible con MySQL 8.0 y versiones posteriores. Dado que versiones anteriores no soportan la cláusula WITH, es necesario considerar alternativas.
Alternativas:
- Usar subconsultas Usa subconsultas directamente en lugar de la cláusula WITH.
SELECT AVG(total_sales) FROM ( SELECT customer_id, SUM(amount) AS total_sales FROM orders GROUP BY customer_id ) AS sales;
- Crear vistas Si necesitas consultas reutilizables, usar una vista puede ser eficaz.
CREATE VIEW sales_view AS SELECT customer_id, SUM(amount) AS total_sales FROM orders GROUP BY customer_id; SELECT AVG(total_sales) FROM sales_view;
Cómo usar correctamente la cláusula WITH
- Priorizar la legibilidad El propósito de la cláusula WITH es organizar consultas y mejorar la legibilidad. Un uso excesivo puede hacer que las consultas sean más complejas, por lo que debe usarse solo cuando sea necesario.
- Verificar el rendimiento Revisa el plan de ejecución (el comando
EXPLAIN) y considera cómo optimizar el rendimiento.EXPLAIN WITH sales AS ( SELECT product_id, SUM(amount) AS total_sales FROM orders GROUP BY product_id ) SELECT * FROM sales WHERE total_sales > 1000;
6. Casos de uso prácticos en escenarios del mundo real
Agregación de datos de ventas
A continuación se muestra un ejemplo de agregación de datos de ventas por mes y luego usar ese resultado para calcular el promedio mensual de ventas.
Ejemplo: Agregación de ventas mensuales y cálculo del promedio
WITH monthly_sales AS (
SELECT
DATE_FORMAT(order_date, '%Y-%m') AS sales_month,
SUM(amount) AS total_sales
FROM orders
GROUP BY sales_month
)
SELECT
sales_month,
total_sales,
AVG(total_sales) OVER () AS average_sales
FROM monthly_sales;
En esta consulta, monthly_sales calcula las ventas por mes, y a partir de ese resultado se calcula el promedio general de ventas. Esto permite que los datos se organicen de forma clara y simplifica el análisis.
Filtrado de datos según condiciones específicas
Al separar la lógica de filtrado compleja en una cláusula WITH, se puede mejorar la legibilidad.
Ejemplo: Crear una lista de clientes de alto gasto
WITH customer_totals AS (
SELECT
customer_id,
SUM(amount) AS total_spent
FROM orders
GROUP BY customer_id
)
SELECT
customer_id,
total_spent
FROM customer_totals
WHERE total_spent > 100000;
En esta consulta, customer_totals calcula el monto total de compra por cliente, y se extraen los clientes que cumplen la condición especificada.
Análisis de datos jerárquicos
Al analizar datos jerárquicos, como estructuras organizacionales o categorías, las cláusulas WITH recursivas son extremadamente útiles.
Ejemplo: Obtener una lista de subordinados directos e indirectos
WITH RECURSIVE employee_hierarchy AS (
SELECT
employee_id,
name,
manager_id,
1 AS level
FROM employees
WHERE manager_id IS NULL
UNION ALL
SELECT
e.employee_id,
e.name,
e.manager_id,
eh.level + 1
FROM employees e
INNER JOIN employee_hierarchy eh
ON e.manager_id = eh.employee_id
)
SELECT
employee_id,
name,
manager_id,
level
FROM employee_hierarchy
ORDER BY level, manager_id;
Esta consulta construye datos jerárquicos en employee_hierarchy y recupera a los empleados agrupados por nivel. Permite la generación dinámica de información similar a un organigrama.
Análisis avanzado usando múltiples CTEs
Al aprovechar múltiples cláusulas WITH, los datos pueden procesarse paso a paso, lo que simplifica el análisis complejo.
Ejemplo: Extraer los productos más vendidos por categoría
WITH category_sales AS (
SELECT
category_id,
product_id,
SUM(amount) AS total_sales
FROM orders
GROUP BY category_id, product_id
),
ranked_sales AS (
SELECT
category_id,
product_id,
total_sales,
RANK() OVER (PARTITION BY category_id ORDER BY total_sales DESC) AS rank
FROM category_sales
)
SELECT
category_id,
product_id,
total_sales
FROM ranked_sales
WHERE rank <= 3;
En esta consulta, se calculan las ventas por categoría y se extraen los tres productos principales dentro de cada categoría. Este enfoque es eficaz al reducir los datos según condiciones específicas.
Puntos clave para la aplicación práctica
- Diseñar consultas en etapas lógicas Utilice la cláusula WITH para dividir las consultas y procesar los datos paso a paso manteniendo la legibilidad.
- Extraer solo los datos necesarios Utilice cláusulas WHERE y LIMIT para evitar procesar datos innecesarios y diseñar consultas eficientes.
- Aplicaciones empresariales flexibles La cláusula WITH puede aplicarse de manera flexible al análisis de ventas, segmentación de clientes, gestión de inventario y más.

7. Preguntas frecuentes (FAQ)
Q1: ¿Cuándo debería usar la cláusula WITH?
A1:
La cláusula WITH es especialmente eficaz en los siguientes escenarios:
- Cuando desea simplificar subconsultas complejas.
- Cuando necesita reutilizar el mismo conjunto de datos varias veces dentro de una consulta.
- Cuando desea dividir lógicamente una consulta para mejorar la legibilidad.
Por ejemplo, en consultas que utilizan los mismos resultados de agregación varias veces, la cláusula WITH permite una organización más eficiente.
Q2: ¿Cuándo es útil un CTE recursivo?
A2:
Los CTE recursivos son útiles al manejar estructuras jerárquicas o cálculos iterativos. Específicamente:
- Procesar datos jerárquicos (p. ej., árboles organizacionales, estructuras de categorías).
- Mostrar jerarquías de carpetas o archivos.
- Cálculos secuenciales de números o periodos de tiempo (p. ej., calcular la secuencia de Fibonacci).
El uso de CTE recursivos facilita la expansión y el procesamiento de datos autorreferenciales.
Q3: ¿Las consultas que usan la cláusula WITH son más eficientes que las vistas?
A3:
Depende del caso de uso.
- Cláusula WITH : Crea un conjunto de resultados temporal utilizado solo dentro de la consulta. Adecuado para datos que no necesitan reutilización frecuente.
- Vista : Almacenada permanentemente en la base de datos y reutilizable por otras consultas. Adecuada para consultas que se usan repetidamente.
Es importante elegir el método apropiado dependiendo del escenario.
Q4: ¿Qué causa la degradación del rendimiento al usar la cláusula WITH?
A4:
Las principales causas de degradación del rendimiento al usar la cláusula WITH incluyen:
- Recálculo de CTE : Los resultados se recalculan cada vez que se referencian, aumentando el tiempo de procesamiento.
- Manejo de conjuntos de datos grandes : Generar conjuntos de datos grandes dentro de la CTE aumenta el uso de memoria y reduce el rendimiento.
- Falta de indexación adecuada : Si las consultas dentro de la CTE no usan índices apropiados, el rendimiento puede ralentizarse.
Contramedidas:
- Considera tablas temporales o vistas si la frecuencia de reutilización es alta.
- Usa cláusulas WHERE y LIMIT para reducir adecuadamente los datos.
Q5: ¿Qué alternativas existen para versiones de MySQL que no soportan la cláusula WITH?
A5:
En versiones anteriores a MySQL 8.0, la cláusula WITH no está soportada, por lo que usa las siguientes alternativas:
- Usa Subconsultas Usa subconsultas directamente en lugar de la cláusula WITH.
SELECT AVG(total_sales) FROM ( SELECT customer_id, SUM(amount) AS total_sales FROM orders GROUP BY customer_id ) AS sales;
- Usa Tablas Temporales Almacena conjuntos de datos reutilizables en una tabla temporal.
CREATE TEMPORARY TABLE temp_sales AS SELECT customer_id, SUM(amount) AS total_sales FROM orders GROUP BY customer_id; SELECT AVG(total_sales) FROM temp_sales;
Q6: ¿Cuáles son las mejores prácticas al usar la cláusula WITH?
A6:
Ten en cuenta las siguientes mejores prácticas:
- Prioriza la simplicidad : No fuerces lógica compleja en una sola cláusula WITH. Divídela apropiadamente.
- Verifica el rendimiento : Verifica el plan de ejecución usando el comando
EXPLAINy optimiza según sea necesario. - Considera la reutilización : Si la frecuencia de reutilización es alta, aprovecha vistas o tablas temporales.
8. Conclusión
Este artículo cubrió la cláusula WITH (Common Table Expression, CTE) introducida en MySQL 8.0, desde los fundamentos hasta aplicaciones avanzadas. La cláusula WITH es una característica extremadamente útil para hacer que las consultas complejas sean concisas y legibles. A continuación, se presentan los puntos clave.
Principales Beneficios de la Cláusula WITH
- Mejora en la Legibilidad de las Consultas Organiza subconsultas complejas, mejorando la legibilidad y mantenibilidad del código SQL.
- Reutilización de Consultas Procesa datos de manera eficiente al referenciar el mismo conjunto de datos múltiples veces.
- Habilita Operaciones de Datos Recursivas Las CTE recursivas simplifican el procesamiento de datos jerárquicos y cálculos iterativos.
Puntos de Uso Práctico
- Útil para análisis de datos de ventas y clientes, permitiendo agregación paso a paso.
- Las CTE recursivas son efectivas para procesamiento de datos jerárquicos (como organigramas o estructuras de categorías).
- Combinar cláusulas WITH con vistas o tablas temporales permite operaciones de base de datos flexibles y eficientes.
Consideraciones Importantes
- La cláusula WITH es poderosa, pero un uso inadecuado puede reducir el rendimiento.
- Evalúa la reutilización y el rendimiento caso por caso, y elige entre vistas o tablas temporales cuando sea apropiado.
- Siempre verifica la eficiencia de la consulta usando el plan de ejecución (comando
EXPLAIN).
Pasos Siguientes
Al usar la cláusula WITH, puedes crear consultas SQL más eficientes y mantenibles. Intenta aplicarla en tus proyectos del mundo real siguiendo estos pasos:
- Comienza con consultas simples y practica estructurándolas usando la cláusula WITH.
- Desafíate con CTE recursivas para datos jerárquicos y escenarios complejos.
- Enfócate en la optimización del rendimiento para mejorar aún más tus habilidades en SQL.
Esto concluye el artículo. Utiliza tu conocimiento de la cláusula WITH de MySQL en tu trabajo diario y estudios.


