DELETE con JOIN
MySQL permite combinar DELETE con JOIN para eliminar filas de una tabla basándote en datos de otra tabla relacionada. Es la contraparte del UPDATE con JOIN y sigue una lógica similar: unes las tablas y después especificas de cuál quieres eliminar filas.
Sintaxis
DELETE tabla1
FROM tabla1
JOIN tabla2 ON tabla1.columna = tabla2.columna
WHERE condicion;La diferencia clave con un DELETE normal es que debes especificar la tabla de la que quieres eliminar antes de la cláusula FROM. El FROM aquí define las tablas involucradas en el JOIN, no la tabla de origen del DELETE.
DELETE con INNER JOIN
Eliminar las etiquetas de productos que pertenecen a la categoría "Novelas":
DELETE ep
FROM etiquetas_producto ep
JOIN productos p ON ep.producto_id = p.id
JOIN categorias c ON p.categoria_id = c.id
WHERE c.nombre = 'Novelas';Query OK, 3 rows affected (0.01 sec)
El JOIN conecta etiquetas con productos y categorías. El DELETE solo afecta a la tabla etiquetas_producto (indicada con el alias ep antes del FROM). Las tablas productos y categorias no se modifican, solo se usan para filtrar.
Los productos de la categoría Novelas son "Cien años de soledad" (etiqueta: clásico, bestseller), "1984" (clásico) y "El nombre del viento". Se eliminan las etiquetas de estos productos.
DELETE con LEFT JOIN
El LEFT JOIN es especialmente útil para eliminar registros huérfanos o sin relación. Eliminar productos que nunca se han vendido:
DELETE p
FROM productos p
LEFT JOIN detalle_pedidos dp ON p.id = dp.producto_id
WHERE dp.id IS NULL;Query OK, 3 rows affected (0.01 sec)
El LEFT JOIN incluye todos los productos. Los que no tienen correspondencia en detalle_pedidos tendrán dp.id IS NULL. Esos productos (los que nunca se vendieron) se eliminan. En nuestra base de datos son el Cargador USB-C 65W, el Sofá 3 plazas y la Estantería modular.
Eliminar de ambas tablas
Puedes eliminar filas de varias tablas a la vez especificando múltiples tablas antes del FROM:
DELETE p, ep
FROM pedidos p
JOIN etiquetas_producto ep ON EXISTS (
SELECT 1 FROM detalle_pedidos dp
WHERE dp.pedido_id = p.id AND dp.producto_id = ep.producto_id
)
WHERE p.estado = 'cancelado';Este ejemplo elimina tanto los pedidos cancelados como las etiquetas de los productos que estaban en esos pedidos. En la práctica, eliminar de múltiples tablas a la vez debe usarse con cuidado, ya que aumenta la complejidad y el riesgo de eliminar datos no deseados.
Una alternativa más segura es hacer los DELETE por separado:
-- Primero eliminar las etiquetas relacionadas
DELETE ep
FROM etiquetas_producto ep
JOIN detalle_pedidos dp ON ep.producto_id = dp.producto_id
JOIN pedidos p ON dp.pedido_id = p.id
WHERE p.estado = 'cancelado';
-- Después eliminar los pedidos
DELETE FROM pedidos WHERE estado = 'cancelado';Eliminar duplicados
Un uso práctico del DELETE con JOIN es eliminar filas duplicadas manteniendo solo una. Si la tabla de etiquetas tuviera duplicados accidentales:
DELETE ep1
FROM etiquetas_producto ep1
JOIN etiquetas_producto ep2
ON ep1.producto_id = ep2.producto_id
AND ep1.etiqueta = ep2.etiqueta
AND ep1.id > ep2.id;El self-join encuentra pares de etiquetas con el mismo producto y la misma etiqueta. La condición ep1.id > ep2.id garantiza que solo se elimina la fila con el ID mayor, manteniendo la original. Nuestra tabla tiene una restricción UNIQUE que previene duplicados, pero este patrón es útil en tablas sin restricciones.
DELETE JOIN vs subconsulta
Ambos enfoques eliminan las reseñas de productos de una categoría específica:
-- Con JOIN (preferido para condiciones complejas)
DELETE r
FROM resenas r
JOIN productos p ON r.producto_id = p.id
WHERE p.categoria_id = 6;
-- Con subconsulta (alternativa)
DELETE FROM resenas
WHERE producto_id IN (
SELECT id FROM productos WHERE categoria_id = 6
);El JOIN es más versátil cuando necesitas acceder a columnas de varias tablas en la condición. La subconsulta es más directa para condiciones simples.
Verificar antes de eliminar
Al igual que con cualquier DELETE, verifica primero lo que vas a eliminar:
-- Ver qué se eliminará
SELECT ep.id, p.nombre, ep.etiqueta
FROM etiquetas_producto ep
JOIN productos p ON ep.producto_id = p.id
JOIN categorias c ON p.categoria_id = c.id
WHERE c.nombre = 'Fitness';
-- Si es correcto, ejecutar
DELETE ep
FROM etiquetas_producto ep
JOIN productos p ON ep.producto_id = p.id
JOIN categorias c ON p.categoria_id = c.id
WHERE c.nombre = 'Fitness';Convierte tu DELETE en un SELECT con las mismas tablas y condiciones. Si el SELECT muestra exactamente las filas que quieres eliminar, puedes ejecutar el DELETE con confianza.
En el siguiente artículo veremos la sentencia REPLACE, que combina DELETE e INSERT en una sola operación.
Escrito por Eduardo Lázaro
