INTERSECT
El operador INTERSECT devuelve las filas que aparecen en ambas consultas. Es la intersección de conjuntos: solo se mantienen las filas que existen tanto en el primer SELECT como en el segundo.
MySQL soporta INTERSECT desde la versión 8.0.31. En versiones anteriores, puedes conseguir el mismo resultado con INNER JOIN o con IN y subconsultas.
Sintaxis
SELECT columnas FROM tabla1
INTERSECT
SELECT columnas FROM tabla2;Al igual que con UNION, ambas consultas deben devolver el mismo número de columnas. INTERSECT elimina duplicados automáticamente (se comporta como INTERSECT DISTINCT). Si necesitas mantener duplicados, puedes usar INTERSECT ALL.
Productos premium que son más vendidos
Los productos que tienen simultáneamente las etiquetas "premium" y "más vendido":
SELECT p.nombre, p.precio
FROM productos p
JOIN etiquetas_producto ep ON p.id = ep.producto_id
WHERE ep.etiqueta = 'premium'
INTERSECT
SELECT p.nombre, p.precio
FROM productos p
JOIN etiquetas_producto ep ON p.id = ep.producto_id
WHERE ep.etiqueta = 'más vendido';| nombre | precio |
|---|---|
| iPhone 15 Pro | 1299.99 |
De los 4 productos premium y los 5 más vendidos, solo el iPhone 15 Pro tiene ambas etiquetas. El INTERSECT descarta los productos que solo aparecen en uno de los dos conjuntos.
Productos vendidos y reseñados
Productos que se han vendido al menos una vez y que también tienen al menos una reseña:
SELECT DISTINCT p.nombre
FROM productos p
JOIN detalle_pedidos dp ON p.id = dp.producto_id
INTERSECT
SELECT DISTINCT p.nombre
FROM productos p
JOIN resenas r ON p.id = r.producto_id
ORDER BY nombre
LIMIT 8;| nombre |
|---|
| ASUS ROG Zephyrus |
| Cable USB-C a Lightning |
| Camiseta algodón básica |
| Clean Code |
| Escritorio ajustable |
| Esterilla yoga premium |
| Google Pixel 8 |
| iPhone 15 Pro |
Solo los productos que aparecen en ambas tablas (detalle_pedidos y resenas) pasan el filtro. Los productos que se vendieron pero nadie reseñó, o que fueron reseñados sin haberse vendido, quedan fuera.
Clientes compradores y opinadores
Clientes que han realizado al menos un pedido y han dejado al menos una reseña:
SELECT cl.nombre, cl.apellidos
FROM clientes cl
JOIN pedidos p ON cl.id = p.cliente_id
INTERSECT
SELECT cl.nombre, cl.apellidos
FROM clientes cl
JOIN resenas r ON cl.id = r.cliente_id
ORDER BY nombre;| nombre | apellidos |
|---|---|
| Ana | Martínez Ruiz |
| Andrés | Vega Romero |
| Carlos | Rodríguez Martín |
| David | Sánchez Moreno |
| Isabel | Gil Molina |
| Javier | Moreno Díaz |
| Laura | López Sánchez |
| Lucía | Díaz Hernández |
| María | García López |
| Miguel | Hernández Torres |
| Pedro | Fernández Castro |
| Sara | Torres Vega |
12 clientes han hecho ambas cosas: comprar y opinar. Los clientes que solo compraron pero no dejaron reseña (como Carmen, Elena, etc.) y Diego (que reseñó un producto pero nunca compró) quedan excluidos.
Alternativa con INNER JOIN
En versiones de MySQL anteriores a 8.0.31 (o cuando prefieras mayor compatibilidad), puedes emular INTERSECT con un INNER JOIN:
-- Equivalente al INTERSECT de productos premium + más vendidos
SELECT DISTINCT p.nombre, p.precio
FROM productos p
JOIN etiquetas_producto ep1 ON p.id = ep1.producto_id
JOIN etiquetas_producto ep2 ON p.id = ep2.producto_id
WHERE ep1.etiqueta = 'premium'
AND ep2.etiqueta = 'más vendido';Otra alternativa es usar IN con una subconsulta:
SELECT p.nombre, p.precio
FROM productos p
JOIN etiquetas_producto ep ON p.id = ep.producto_id
WHERE ep.etiqueta = 'premium'
AND p.id IN (
SELECT producto_id
FROM etiquetas_producto
WHERE etiqueta = 'más vendido'
);Las tres formas producen el mismo resultado. INTERSECT es más legible cuando las dos consultas tienen estructuras muy diferentes. INNER JOIN o IN pueden ser más intuitivos cuando la relación entre los conjuntos es directa.
INTERSECT con múltiples consultas
Puedes encadenar varios INTERSECT:
-- Productos que tienen las tres etiquetas: premium, más vendido y novedad
SELECT producto_id FROM etiquetas_producto WHERE etiqueta = 'premium'
INTERSECT
SELECT producto_id FROM etiquetas_producto WHERE etiqueta = 'más vendido'
INTERSECT
SELECT producto_id FROM etiquetas_producto WHERE etiqueta = 'novedad';| producto_id |
|---|
| 1 |
El producto 1 (iPhone 15 Pro) es el único que tiene las tres etiquetas simultáneamente.
Practica con INTERSECT
Usa el editor para encontrar elementos comunes entre consultas:
En el siguiente artículo veremos EXCEPT, que devuelve las filas de la primera consulta que no aparecen en la segunda.
Escrito por Eduardo Lázaro
