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;
nombreprecio
ASUS ROG Zephyrus1899.99
Lenovo ThinkPad X11549.00
MacBook Air M31399.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;
nombreprecio
ASUS ROG Zephyrus1899.99
Lenovo ThinkPad X11549.00
MacBook Air M31399.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;
nombrepuestosalario
RicardoDirector General75000
SofíaDirectora de Ventas55000

> 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;
nombrepuestosalario
NataliaVendedora Senior38000
CristinaResponsable de Almacén35000
DanielVendedor32000
PatriciaVendedora32000
RaúlVendedor Junior28000
MarcosOperario de Almacén26000
InésOperaria de Almacén26000

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
);
nombreprecio
iPhone 15 Pro1299.99
Samsung Galaxy S24899.99
Google Pixel 8699.00
Xiaomi 14599.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