IN
El operador IN comprueba si un valor coincide con cualquiera de los valores de una lista. Es una forma concisa de escribir múltiples condiciones OR sobre la misma columna.
Sintaxis
SELECT columnas
FROM tabla
WHERE columna IN (valor1, valor2, valor3, ...);La lista de valores va entre paréntesis, separados por comas. Si el valor de la columna coincide con alguno de los valores de la lista, la condición es verdadera y la fila se incluye en el resultado.
IN con valores numéricos
Para obtener los productos de las categorías Smartphones (6), Portátiles (7) y Accesorios electrónicos (8):
SELECT nombre, precio, categoria_id
FROM productos
WHERE categoria_id IN (6, 7, 8);| nombre | precio | categoria_id |
|---|---|---|
| iPhone 15 Pro | 1299.99 | 6 |
| Samsung Galaxy S24 | 899.99 | 6 |
| Google Pixel 8 | 699.00 | 6 |
| Xiaomi 14 | 599.99 | 6 |
| MacBook Air M3 | 1399.00 | 7 |
| Lenovo ThinkPad X1 | 1549.00 | 7 |
| ASUS ROG Zephyrus | 1899.99 | 7 |
| Funda iPhone silicona | 49.99 | 8 |
| Cargador USB-C 65W | 35.99 | 8 |
| Cable USB-C a Lightning | 19.99 | 8 |
Esto es equivalente a escribir WHERE categoria_id = 6 OR categoria_id = 7 OR categoria_id = 8, pero mucho más legible, especialmente cuando la lista tiene muchos valores.
IN con cadenas de texto
IN funciona también con cadenas. Para buscar clientes de tres ciudades concretas:
SELECT nombre, apellidos, ciudad
FROM clientes
WHERE ciudad IN ('Madrid', 'Barcelona', 'Sevilla');| nombre | apellidos | ciudad |
|---|---|---|
| María | García López | Madrid |
| Carlos | Rodríguez Martín | Barcelona |
| Ana | Martínez Ruiz | Sevilla |
| Pedro | Fernández Castro | Madrid |
| Laura | López Sánchez | Barcelona |
Los valores de texto se comparan respetando la collation de la columna. Con la collation por defecto de MySQL (utf8mb4_0900_ai_ci), la comparación no distingue mayúsculas y minúsculas, así que 'madrid' y 'Madrid' se tratan como iguales.
IN con subconsultas
Una de las funcionalidades más potentes de IN es que la lista de valores puede venir de otra consulta. En lugar de escribir los valores a mano, usas una subconsulta que los genera dinámicamente:
SELECT nombre, precio
FROM productos
WHERE categoria_id IN (
SELECT id
FROM categorias
WHERE categoria_padre_id = 1
);| nombre | precio |
|---|---|
| iPhone 15 Pro | 1299.99 |
| Samsung Galaxy S24 | 899.99 |
| Google Pixel 8 | 699.00 |
| Xiaomi 14 | 599.99 |
| MacBook Air M3 | 1399.00 |
| Lenovo ThinkPad X1 | 1549.00 |
| ASUS ROG Zephyrus | 1899.99 |
| Funda iPhone silicona | 49.99 |
| Cargador USB-C 65W | 35.99 |
| Cable USB-C a Lightning | 19.99 |
La subconsulta obtiene los IDs de las subcategorías de Electrónica (categoría padre 1), que son 6, 7 y 8. Después, la consulta principal filtra los productos que pertenecen a esas categorías. El resultado es el mismo que el primer ejemplo, pero esta vez no necesitamos conocer los IDs de antemano.
Otro ejemplo: productos que han aparecido en al menos un pedido:
SELECT DISTINCT nombre, precio
FROM productos
WHERE id IN (
SELECT producto_id
FROM detalle_pedidos
)
ORDER BY nombre;La subconsulta devuelve los IDs de todos los productos que están en algún detalle de pedido. La consulta principal muestra solo esos productos.
IN con valores numéricos mixtos
IN acepta cualquier expresión, no solo constantes:
SELECT nombre, precio
FROM productos
WHERE precio IN (19.99, 29.99, 39.99, 49.99);| nombre | precio |
|---|---|
| Funda iPhone silicona | 49.99 |
| Cable USB-C a Lightning | 19.99 |
| Sartén antiadherente 28cm | 39.99 |
| Esterilla yoga premium | 29.99 |
| Banda elástica set x5 | 19.99 |
| Clean Code | 39.99 |
| Diseño de APIs | 29.99 |
Todos los productos que cuestan exactamente alguno de esos precios.
IN y NULL
Es importante entender cómo se comporta IN con valores NULL. Si la lista contiene un NULL, no afecta a las filas con valores no nulos, pero si el valor de la columna es NULL, el resultado es NULL (no verdadero):
SELECT nombre, telefono
FROM clientes
WHERE telefono IN ('612345678', NULL);| nombre | telefono |
|---|---|
| María | 612345678 |
Solo aparece María (cuyo teléfono coincide con el valor de la lista). Los clientes con telefono = NULL no aparecen, porque NULL IN (...) devuelve NULL, no TRUE. Para incluir valores nulos necesitas IS NULL explícitamente:
WHERE telefono IN ('612345678') OR telefono IS NULLRendimiento de IN
Con listas pequeñas (decenas de valores), IN es muy eficiente. MySQL puede usar índices sobre la columna para evaluar la condición rápidamente.
Con subconsultas, el rendimiento depende de cómo MySQL optimice la consulta. En versiones modernas (8.0+), MySQL suele convertir las subconsultas de IN en semi-joins internamente, lo que las hace comparables en rendimiento a un JOIN explícito. En versiones muy antiguas, las subconsultas correlacionadas dentro de IN podían ser lentas.
Si la lista tiene miles de valores, considera usar una tabla temporal o un JOIN en lugar de un IN con una lista enorme.
IN vs OR
Estas dos consultas son equivalentes:
-- Con IN
WHERE estado IN ('pendiente', 'procesando', 'enviado')
-- Con OR
WHERE estado = 'pendiente'
OR estado = 'procesando'
OR estado = 'enviado'IN es preferible por legibilidad cuando comparas la misma columna contra varios valores. OR es necesario cuando las condiciones involucran diferentes columnas o expresiones.
Practica con IN
Usa el editor para probar IN con distintas listas de valores. Intenta filtrar productos por categoría o pedidos por estado:
En el siguiente artículo veremos NOT IN, la negación de IN.
Escrito por Eduardo Lázaro
