ANY / ALL
Los operadores ANY y ALL permiten comparar un valor contra un conjunto de valores devuelto por una subconsulta. Mientras que IN solo comprueba igualdad, ANY y ALL funcionan con cualquier operador de comparación: =, >, <, >=, <= y !=.
ANY devuelve TRUE si la comparación se cumple para al menos uno de los valores del conjunto. ALL devuelve TRUE solo si se cumple para todos los valores.
Sintaxis
SELECT columnas
FROM tabla
WHERE valor operador ANY (subconsulta);
SELECT columnas
FROM tabla
WHERE valor operador ALL (subconsulta);La subconsulta debe devolver una sola columna. El operador puede ser cualquiera de los de comparación estándar.
ANY: al menos uno
> ANY (subconsulta) significa "mayor que al menos uno de los valores", es decir, mayor que el mínimo del conjunto. Productos de fuera de la categoría Smartphones que cuestan más que al menos un smartphone:
SELECT nombre, precio
FROM productos
WHERE precio > ANY (
SELECT precio
FROM productos
WHERE categoria_id = 6
)
AND categoria_id != 6
ORDER BY precio DESC;| nombre | precio |
|---|---|
| ASUS ROG Zephyrus | 1899.99 |
| Lenovo ThinkPad X1 | 1549.00 |
| MacBook Air M3 | 1399.00 |
Los smartphones tienen precios de 599.99, 699.00, 899.99 y 1299.99 euros. La condición > ANY busca productos con precio mayor que al menos uno de esos valores, es decir, mayor que 599.99 (el mínimo). Solo los tres portátiles superan ese umbral. El Sofá 3 plazas (599.00) no entra porque 599.00 no es mayor que 599.99.
ALL: todos
> ALL (subconsulta) significa "mayor que todos los valores", es decir, mayor que el máximo del conjunto. Productos más caros que todos los smartphones:
SELECT nombre, precio
FROM productos
WHERE precio > ALL (
SELECT precio
FROM productos
WHERE categoria_id = 6
)
ORDER BY precio DESC;| nombre | precio |
|---|---|
| ASUS ROG Zephyrus | 1899.99 |
| Lenovo ThinkPad X1 | 1549.00 |
| MacBook Air M3 | 1399.00 |
En este caso, > ALL exige que el precio supere 1299.99 (el máximo de los smartphones). El resultado coincide con el ejemplo anterior porque los tres portátiles también superan al smartphone más caro, pero la lógica es diferente: aquí se compara contra el máximo, no contra el mínimo.
Diferencia entre ANY y ALL
La diferencia se aprecia mejor cuando los resultados divergen. Los puestos con "Director" en la tabla de empleados son: Ricardo (Director General, 75000), Sofía (Directora de Ventas, 55000) y Alberto (Director de Logística, 52000).
Empleados que ganan más que al menos un director:
SELECT nombre, puesto, salario
FROM empleados
WHERE salario > ANY (
SELECT salario
FROM empleados
WHERE puesto LIKE 'Director%'
)
ORDER BY salario DESC;| nombre | puesto | salario |
|---|---|---|
| Ricardo | Director General | 75000 |
| Sofía | Directora de Ventas | 55000 |
> ANY busca salarios mayores que el mínimo del conjunto (52000). Ricardo gana más que Alberto y Sofía. Sofía gana más que Alberto. Alberto gana exactamente 52000, que no es mayor que 52000, así que no aparece. Los demás empleados ganan menos de 52000.
Ahora, empleados que ganan más que todos los directores:
SELECT nombre, puesto, salario
FROM empleados
WHERE salario > ALL (
SELECT salario
FROM empleados
WHERE puesto LIKE 'Director%'
)
ORDER BY salario DESC;Empty set (0.00 sec)
> ALL exige superar el máximo del conjunto (75000). Nadie gana más que Ricardo, así que el resultado está vacío. Esta es la diferencia clave: > ANY compara contra el mínimo y > ALL contra el máximo.
Empleados con salario inferior a todos los directores
< ALL significa "menor que el mínimo del conjunto". Empleados que ganan menos que todos los directores:
SELECT nombre, puesto, salario
FROM empleados
WHERE salario < ALL (
SELECT salario
FROM empleados
WHERE puesto LIKE 'Director%'
)
ORDER BY salario DESC;| nombre | puesto | salario |
|---|---|---|
| Natalia | Vendedora Senior | 38000 |
| Cristina | Responsable de Almacén | 35000 |
| Daniel | Vendedor | 32000 |
| Patricia | Vendedora | 32000 |
| Raúl | Vendedor Junior | 28000 |
| Marcos | Operario de Almacén | 26000 |
| Inés | Operaria de Almacén | 26000 |
El director con menor salario es Alberto con 52000. Los 7 empleados listados ganan todos menos de 52000. Solo los propios directores quedan excluidos del resultado.
= ANY es equivalente a IN
El operador = ANY es funcionalmente idéntico a IN. Estas dos consultas producen exactamente el mismo resultado:
-- Con IN
SELECT nombre, precio
FROM productos
WHERE categoria_id IN (
SELECT categoria_id
FROM productos
GROUP BY categoria_id
HAVING COUNT(*) >= 4
);
-- Con = ANY (equivalente)
SELECT nombre, precio
FROM productos
WHERE categoria_id = ANY (
SELECT categoria_id
FROM productos
GROUP BY categoria_id
HAVING COUNT(*) >= 4
);| nombre | precio |
|---|---|
| iPhone 15 Pro | 1299.99 |
| Samsung Galaxy S24 | 899.99 |
| Google Pixel 8 | 699.00 |
| Xiaomi 14 | 599.99 |
Solo la categoría 6 (Smartphones) tiene 4 o más productos. Ambas formas devuelven los mismos 4 smartphones. En la práctica, IN es la forma preferida por ser más legible.
ALL es equivalente a NOT IN
De la misma manera, <> ALL (distinto de todos) equivale a NOT IN:
-- Con NOT IN
SELECT nombre
FROM clientes
WHERE id NOT IN (
SELECT DISTINCT cliente_id FROM pedidos
);
-- Con <> ALL (equivalente)
SELECT nombre
FROM clientes
WHERE id <> ALL (
SELECT DISTINCT cliente_id FROM pedidos
);| nombre |
|---|
| Diego |
Diego es el único cliente sin pedidos. Ambas formas son equivalentes, pero recuerda que NOT IN tiene problemas con NULLs (como explicamos en el artículo de EXISTS). Por eso <> ALL hereda el mismo problema: si la subconsulta devuelve algún NULL, el resultado puede ser inesperado.
SOME es sinónimo de ANY
MySQL acepta SOME como sinónimo de ANY. Las siguientes expresiones son idénticas:
WHERE precio > ANY (subconsulta)
WHERE precio > SOME (subconsulta)SOME existe por compatibilidad con el estándar SQL. En la práctica, casi todo el mundo usa ANY.
Cuándo usar ANY y ALL
ANY y ALL son útiles cuando necesitas comparar con operadores distintos de la igualdad (>, <, >=, <=). Para la igualdad, IN es más legible que = ANY. Para la desigualdad, NOT EXISTS es más seguro que <> ALL porque no tiene problemas con NULLs.
Los casos donde ANY y ALL realmente brillan son las comparaciones de rango: "productos más caros que todos los de una categoría", "empleados que ganan más que al menos un director", o "pedidos con importe superior a todos los pedidos cancelados".
Con esto completamos la sección de subconsultas. En la siguiente sección exploraremos las sentencias de manipulación de datos: INSERT, UPDATE, DELETE y más operaciones para modificar los datos de las tablas.
Escrito por Eduardo Lázaro
