- 1 1. Introducción
- 2 2. Conocimientos básicos de la cláusula WITH (expresión de tabla común)
- 3 3. Uso básico de la cláusula WITH en MySQL
- 4 4. Ejemplos de aplicación de la cláusula WITH recursiva
- 5 5. Precauciones al usar la cláusula WITH
- 6 6. Ejemplos de aplicación en la práctica profesional
- 7 7. Preguntas frecuentes (FAQ)
- 7.1 Q1: ¿En qué casos se debería usar la cláusula WITH?
- 7.2 Q2: ¿En qué casos es útil un CTE recursivo?
- 7.3 Q3: ¿Es una consulta con cláusula WITH más eficiente que una vista?
- 7.4 Q4: ¿Cuáles son las causas de la disminución de rendimiento al usar la cláusula WITH?
- 7.5 Q5: ¿Hay medios alternativos 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. Resumen
1. Introducción
MySQL es un sistema de gestión de bases de datos utilizado por muchos desarrolladores y administradores de bases de datos, que proporciona funciones SQL potentes y flexibles. En particular, la cláusula WITH introducida en MySQL 8.0 (expresión de tabla común, Common Table Expression: CTE) es una herramienta poderosa para hacer que las consultas SQL sean más legibles y mejorar su mantenibilidad.
En este artículo, explicaremos en detalle desde lo básico hasta lo avanzado de esta cláusula WITH, dirigido a principiantes y usuarios intermedios. En particular, cubriremos temas prácticos como el reemplazo de subconsultas y la implementación de consultas recursivas.
Para aquellos que están aprendiendo SQL o que luchan con la optimización de consultas en su trabajo diario, este artículo busca proporcionar soluciones concretas. Siga el contenido a continuación para entender los fundamentos de la cláusula WITH y aplicarlos en la práctica.
2. Conocimientos básicos de la cláusula WITH (expresión de tabla común)
¿Qué es la cláusula WITH?
La cláusula WITH es una sintaxis para definir un conjunto de resultados temporal (expresión de tabla común, CTE) dentro de una consulta SQL y utilizarlo en consultas subsiguientes. Está soportada desde MySQL 8.0 y permite reemplazar subconsultas complejas con una forma más concisa y fácil de entender.
Por ejemplo, si se escribe una subconsulta directamente, la legibilidad disminuye y la consulta completa tiende a ser larga. Usando la cláusula WITH, se puede dividir la consulta en bloques lógicos, lo que la hace más fácil de entender.
Sintaxis básica de la cláusula WITH
A continuación se muestra la sintaxis básica de la cláusula WITH.
WITH tabla AS (
SELECT columna1, columna2
FROM tabla_original
WHERE condicion
)
SELECT columna1, columna2
FROM tabla;
En esta sintaxis, después de WITH
se define una tabla virtual (expresión de tabla común) y se utiliza en la consulta principal. Esto permite expresar subconsultas que se usan repetidamente de manera 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.
Característica | Cláusula WITH | Subconsulta | Vista |
---|---|---|---|
Alcance | Solo válido dentro de la consulta | Solo utilizable en el lugar definido | Reutilizable en toda la base de datos |
Temporalidad | Temporal | Temporal | Permanente |
Uso | Simplificar consultas complejas | Extracción de datos temporal | Extracción de datos reutilizada frecuentemente |
La cláusula WITH tiene mayor legibilidad que las subconsultas y es ideal cuando no es necesario crear objetos permanentes como las vistas.
Ventajas de usar la cláusula WITH
- Mejora de la legibilidad de la consulta
Incluso si hay múltiples subconsultas, organizándolas con la cláusula WITH, la estructura se vuelve clara. - Mejora de la reutilización
Al definir un conjunto de resultados temporal, se puede referenciar múltiples veces dentro de la consulta. - Mejora del mantenimiento
Como se puede dividir la consulta lógicamente, las correcciones y extensiones son más fáciles.
3. Uso básico de la cláusula WITH en MySQL
Reemplazo de subconsultas
La cláusula WITH es una herramienta poderosa para simplificar subconsultas complejas. Si se incrustan directamente las subconsultas, toda la consulta se vuelve compleja y difícil de leer, pero al usar la cláusula WITH, se puede mejorar la legibilidad.
A continuación, se muestra un ejemplo básico de reemplazo de subconsultas usando la cláusula WITH.Caso con subconsulta:
SELECT AVG(sales.total) AS average_sales
FROM (
SELECT SUM(amount) AS total
FROM orders
GROUP BY customer_id
) AS sales;
Caso con 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
con la cláusula WITH y se utiliza en la consulta principal. Esto hace que toda la consulta sea más clara y organizada.
Definición de múltiples expresiones de tabla común (CTE)
Con la cláusula WITH, es posible definir múltiples CTE. Esto permite modularizar aún más las 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, se calcula la suma total de ventas por cliente en sales_per_customer
, y basado en eso, se extraen los clientes de alto valor en high_value_customers
. Al utilizar múltiples CTE de manera secuencial, se puede construir la consulta de forma paso a paso.
Método de uso de CTE anidadas
Al usar CTE anidadas, se pueden realizar operaciones de datos aún más complejas.Ejemplo:
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, se agregan las ventas por producto en sales_data
, y se realiza el ranking de ventas en ranked_sales
. Finalmente, se extraen los 5 productos principales.
Puntos clave para el uso básico en la práctica
- Dividir y pensar en la consulta
Al construir CTE de manera paso a paso, se hace la consulta más legible y facilita la depuración. - Guardar resultados de cálculos temporales
Al agrupar en CTE los resultados de cálculos o condiciones de filtrado que se usan múltiples veces, se puede reducir la duplicación de código. - Precauciones con datos a gran escala
Dado que las CTE generan conjuntos de resultados temporales, al manejar grandes volúmenes de datos, es necesario considerar el impacto en el rendimiento.
4. Ejemplos de aplicación de la cláusula WITH recursiva
¿Qué es la cláusula WITH recursiva?
La cláusula WITH recursiva (CTE recursiva) es un método que utiliza expresiones de tabla común para ejecutar consultas de manera autoreferencial de forma repetida, procesando datos jerárquicos o cálculos iterativos. La CTE recursiva está soportada en MySQL 8.0 y versiones posteriores, y es particularmente útil para manejar datos con relaciones padre-hijo o estructuras jerárquicas.
Sintaxis básica de la CTE recursiva
Al definir una CTE recursiva, se utiliza la palabra clave WITH RECURSIVE
. La sintaxis básica es la siguiente:
WITH RECURSIVE nombre_tabla_recursiva AS (
consulta_inicial -- Punto de inicio de la recursión
UNION ALL
consulta_recursiva -- Consulta invocada recursivamente
)
SELECT * FROM nombre_tabla_recursiva;
- Consulta inicial: Obtiene el primer conjunto de datos del procesamiento recursivo.
- Consulta recursiva: Genera nuevos datos basados en la consulta inicial o en los resultados anteriores.
- UNION ALL: Combina los resultados de la consulta inicial y la consulta recursiva.
Ejemplo de procesamiento de datos jerárquicos
La CTE recursiva se utiliza para expandir datos con estructura jerárquica (por ejemplo, árboles organizacionales o árboles de categorías).Ejemplo: Expandir la jerarquía de gestión de empleadosConsideremos la siguiente tabla employees
:
employee_id | name | manager_id |
---|---|---|
1 | Alice | NULL |
2 | Bob | 1 |
3 | Charlie | 1 |
4 | David | 2 |
Usando estos datos, creamos una consulta para obtener toda la jerarquía a partir de un empleado determinado.
WITH RECURSIVE employee_hierarchy AS (
-- Consulta inicial: Obtener empleados de nivel superior
SELECT employee_id, name, manager_id, 1 AS level
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Consulta recursiva: Obtener subordinados directos
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;
Resultado:
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, se busca recursivamente subordinados basados en manager_id
y se expande toda la jerarquía.
Limitaciones y precauciones de la CTE recursiva
- Se necesita una condición de terminación para la recursión
Si la consulta recursiva no cumple con la condición de terminación, puede ocurrir un bucle infinito. Establezca condiciones adecuadas para evitar bucles infinitos. - Impacto en el rendimiento
La CTE recursiva implica muchos cálculos para grandes volúmenes de datos, lo que puede alargar el tiempo de ejecución de la consulta. Utilice cláusulasLIMIT
o condiciones de filtrado para optimizar la eficiencia. - Limitación de profundidad recursiva
En MySQL, hay un límite en la profundidad de la recursión, por lo que se debe tener cuidado con procesos recursivos muy profundos. Esta limitación se puede configurar con el parámetromax_recursive_iterations
.
Escenarios para utilizar CTE recursiva
- Recorrido de estructura de carpetas: Buscar recursivamente carpetas y subcarpetas.
- Creación de organigramas: Visualizar jerarquías de superiores a subordinados.
- Visualización de árboles de categorías: Obtener jerarquías de categorías de productos o etiquetas.
La CTE recursiva es una herramienta poderosa que permite describir consultas SQL de manera concisa y mejorar la legibilidad en estos escenarios.
5. Precauciones al usar la cláusula WITH
Impacto en el rendimiento y optimización
- Recálculo de CTE
Las CTE definidas con la cláusula WITH se recalculan básicamente cada vez que se referencian en la consulta. Por lo tanto, si se utiliza la misma CTE múltiples veces, el tiempo de ejecución de la consulta puede aumentar. 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, es efectivo guardar los resultados en una tabla temporal cuando se referencia múltiples veces.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;
- División de CTE complejas
Si la cláusula WITH se anida demasiado, la consulta completa se complica y el debugging se vuelve difícil. Es importante dividir adecuadamente para que el procesamiento dentro de una CTE no sea excesivamente complejo.
Uso con grandes volúmenes de datos
La cláusula WITH genera conjuntos de datos temporales durante la ejecución. Al manejar grandes volúmenes de datos, esto puede sobrecargar la memoria o el almacenamiento.Métodos de mitigación:
- Filtrar datos con la cláusula WHERE
Al filtrar datos innecesarios dentro de la CTE, se puede reducir la cantidad de cálculos.
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;
- Uso de la cláusula LIMIT
Cuando hay mucho datos, use la cláusulaLIMIT
para extraer solo los datos necesarios.
Compatibilidad con versiones de MySQL
La cláusula WITH de MySQL está soportada desde MySQL 8.0. En versiones anteriores, no se puede usar, por lo que es necesario considerar alternativas.Alternativas:
- Uso de subconsultas
Use 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;
- Creación de vistas
Si se necesitan consultas reutilizables, usar vistas también es efectivo.
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;
Uso adecuado de la cláusula WITH
- Enfatizar la legibilidad
El propósito de usar la cláusula WITH es organizar la consulta y mejorar su legibilidad. Si se usa en exceso, puede complicar la consulta, por lo que úsela solo cuando sea necesario. - Verificación de rendimiento
Verifique el plan de ejecución (comandoEXPLAIN
) y considere métodos para 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. Ejemplos de aplicación en la práctica profesional
Agregación de datos de ventas
Este es un ejemplo que agrega los datos de ventas por mes y, utilizando ese resultado, calcula el promedio de ventas mensual.Ejemplo: Agregación de ventas por mes 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, se calculan las ventas por mes en monthly_sales
y, basándose en eso, se calcula el promedio general de ventas. Esto permite organizar los datos de manera clara y realizar análisis de forma sencilla.
Filtrado de datos basado en condiciones específicas
Al dividir el filtrado con condiciones complejas mediante la cláusula WITH, se puede mejorar la legibilidad.Ejemplo: Creación de lista de clientes de compras altas
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, se calcula el total de compras por cliente en customer_totals
y, de ahí, se extraen los clientes de compras altas que cumplen la condición.
Análisis de datos de estructura jerárquica
Al analizar datos jerárquicos de organizaciones o categorías, la cláusula WITH recursiva es muy útil.Ejemplo: Obtención de lista de subordinados directos en la organización
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;
En esta consulta, se construye la jerarquía de empleados en employee_hierarchy
y se obtiene la lista por nivel de empleado. Esto permite generar dinámicamente información como un organigrama.
Análisis utilizando múltiples expresiones de tabla común
Al utilizar múltiples cláusulas WITH, se puede procesar los datos paso a paso y realizar análisis complejos de manera simple.Ejemplo: Extracción de productos de mayor venta por categoría de producto
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. Es efectivo para filtrar datos bajo condiciones específicas.
Puntos clave al aplicar en la práctica profesional
- Diseño de división de consultas
Al utilizar la cláusula WITH para dividir la consulta y procesar los datos paso a paso, se puede realizar análisis complejos manteniendo la legibilidad. - Extraer solo los datos necesarios
Al utilizar cláusulas WHERE o LIMIT para evitar procesar datos innecesarios, se puede diseñar consultas eficientes. - Uso flexible en el negocio
Análisis de ventas, segmentación de clientes, gestión de inventario, etc., se puede usar de manera flexible según las necesidades del negocio.

7. Preguntas frecuentes (FAQ)
Q1: ¿En qué casos se debería usar la cláusula WITH?
A1: La cláusula WITH es particularmente efectiva en escenarios como los siguientes:
- Cuando se desea describir subconsultas complejas de manera concisa.
- Cuando se necesita usar repetidamente el mismo conjunto de datos en múltiples consultas.
- Cuando se quiere dividir lógicamente la consulta para mejorar su legibilidad.
Por ejemplo, en una consulta que usa el mismo resultado de agregación múltiples veces, el uso de la cláusula WITH permite procesarla de manera eficiente.
Q2: ¿En qué casos es útil un CTE recursivo?
A2: Un CTE recursivo es útil cuando se necesita estructura jerárquica o cálculos repetitivos. Específicamente, se usa en escenarios como los siguientes:
- Procesamiento de datos jerárquicos (por ejemplo: árbol organizacional, expansión de estructura de categorías).
- Visualización jerárquica de carpetas o archivos.
- Cálculos secuenciales de números o períodos (por ejemplo: cálculo de la secuencia de Fibonacci).
Con un CTE recursivo, se puede expandir y procesar fácilmente datos auto-referenciales.
Q3: ¿Es una consulta con cláusula WITH más eficiente que una vista?
A3: Depende del caso.
- Cláusula WITH crea un conjunto de resultados temporal que solo se usa dentro de esa consulta. Es adecuada para datos que no necesitan ser reutilizados frecuentemente.
- Vista se guarda permanentemente en la base de datos y puede reutilizarse en otras consultas. Es adecuada para consultas que se usan repetidamente.
Es importante usarlas según sea necesario.
Q4: ¿Cuáles son las causas de la disminución de rendimiento al usar la cláusula WITH?
A4: Las principales causas de disminución de rendimiento al usar la cláusula WITH son las siguientes:
- Recálculo de CTE: Cada vez que se referencia el resultado de WITH, se recalcula, lo que aumenta el tiempo de procesamiento.
- Procesamiento de grandes volúmenes de datos: Generar grandes cantidades de datos dentro de WITH aumenta el uso de memoria y reduce el rendimiento.
- Falta de índices apropiados: Si las consultas dentro de WITH no tienen índices apropiados, la velocidad de procesamiento puede ser lenta.
Medidas:
- Si la reutilización es frecuente, considerar tablas temporales o vistas.
- Usar cláusulas WHERE o LIMIT para filtrar los datos apropiadamente.
Q5: ¿Hay medios alternativos para versiones de MySQL que no soportan la cláusula WITH?
A5: En versiones de MySQL anteriores a 8.0, la cláusula WITH no está soportada, por lo que se usan los siguientes medios alternativos:
- Uso de subconsultas
En lugar de WITH, usar subconsultas directamente.
SELECT AVG(total_sales)
FROM (
SELECT customer_id, SUM(amount) AS total_sales
FROM orders
GROUP BY customer_id
) AS sales;
- Uso de tablas temporales
Guardar el conjunto de datos a reutilizar 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: Al usar la cláusula WITH, preste atención a los siguientes puntos como mejores prácticas:
- Enfatizar la concisión: No forzar consultas complejas en WITH; dividir y organizar apropiadamente.
- Verificación de rendimiento: Verificar el plan de ejecución (comando
EXPLAIN
) y optimizar la consulta según sea necesario. - Considerar la reutilización: Si la reutilización es frecuente, usar vistas o tablas temporales.
8. Resumen
En este artículo, hemos explicado ampliamente la cláusula WITH (expresiones de tabla común, CTE) introducida en MySQL 8.0, desde los fundamentos hasta las aplicaciones avanzadas. La cláusula WITH es una función muy conveniente para hacer que las consultas complejas sean concisas y fáciles de leer. A continuación, resumimos los puntos importantes de este artículo.
Principales ventajas de la cláusula WITH
- Mejora de la legibilidad de las consultas
Al organizar subconsultas complejas de manera concisa, se mejora la legibilidad y mantenibilidad del código SQL. - Reutilización de consultas
Permite procesar eficientemente el mismo conjunto de datos cuando se referencia varias veces. - Posibilidad de operaciones de datos recursivas
Al aprovechar las CTE recursivas, se puede procesar de manera simple datos jerárquicos o cálculos repetitivos.
Puntos de aprovechamiento en el trabajo práctico
- Análisis de datos de ventas o clientes, donde resulta útil para agregar resultados de manera gradual.
- Procesamiento de datos con estructura jerárquica (como organigramas o estructuras de categorías), donde se puede usar efectivamente las CTE recursivas.
- Al combinar con vistas o tablas temporales según sea necesario, se puede lograr una operación de base de datos flexible y eficiente.
Precauciones al usar
- La cláusula WITH es conveniente, pero si no se usa adecuadamente, puede reducir el rendimiento.
- Considera el uso diferenciado con vistas o tablas temporales caso por caso, teniendo en cuenta la reutilización y el rendimiento.
- Es importante verificar la eficiencia de la consulta confirmando el plan de ejecución (comando
EXPLAIN
).
Pasos siguientes
Al usar la cláusula WITH, se pueden crear consultas SQL más eficientes y con mayor mantenibilidad. Prueba implementarla en proyectos reales. Procede de la siguiente manera:
- Comienza con consultas simples y practica la estructuración con la cláusula WITH.
- Desafíate con CTE recursivas para datos jerárquicos o escenarios complejos.
- Mejora aún más tus habilidades en SQL prestando atención a la optimización del rendimiento.
Con esto, el contenido de este artículo ha concluido. Aplica el conocimiento sobre la cláusula WITH de MySQL en tu trabajo diario o en tu aprendizaje.