Aprende SQL · lección gratuita
BETWEEN e IN son atajos que hacen tus filtros más legibles que una pila de AND/OR. BETWEEN comprueba si un valor cae dentro de un rango continuo (incluyendo ambos extremos), e IN comprueba si un valor coincide con alguno de una lista de valores concretos. Ambos tienen su versión negada (NOT BETWEEN, NOT IN), y IN admite incluso una subconsulta como lista.
x BETWEEN a AND b: equivale a x >= a AND x <= b. Los dos extremos están incluidos.x IN (v1, v2, v3): equivale a x = v1 OR x = v2 OR x = v3.'YYYY-MM-DD', que se comparan alfabéticamente y por eso funcionan en rangos).NOT BETWEEN / NOT IN: niegan la pertenencia al rango o a la lista.IN (subconsulta) permite filtrar por valores que devuelve otro SELECT.precio BETWEEN 1000 AND 5000 incluye tanto 1000 como 5000. Si quieres un extremo abierto, usa comparadores: precio >= 1000 AND precio < 5000. Con fechas en formato 'YYYY-MM-DD', BETWEEN '2022-01-01' AND '2022-12-31' captura todo el año 2022 porque el orden alfabético coincide con el cronológico.
Esta es una de las fuentes de bugs más sutiles de SQL. Si la lista de un NOT IN contiene un NULL, la consulta no devuelve ninguna fila, aunque "deberías" obtener resultados. Por ejemplo SELECT nombre FROM productos WHERE id NOT IN (1, 2, NULL); devuelve 0 filas.
¿Por qué? x NOT IN (1,2,NULL) se expande a x<>1 AND x<>2 AND x<>NULL. Cualquier comparación con NULL da UNKNOWN (ni verdadero ni falso), y algo AND UNKNOWN nunca llega a ser verdadero, así que ninguna fila pasa el filtro. Esto es peligroso cuando la lista viene de una subconsulta sobre una columna que puede contener NULL. Soluciones: filtrar los NULL en la subconsulta (WHERE col IS NOT NULL), o usar NOT EXISTS, que no sufre este problema. La versión positiva IN no tiene esta trampa para las filas que sí coinciden, pero por seguridad evita NULL en listas de NOT IN.
SELECT nombre, salario FROM empleados WHERE salario BETWEEN 5000 AND 9000
-- Rango numérico inclusivo: salarios entre 5000 y 8000
SELECT nombre, cargo, salario FROM empleados
WHERE salario BETWEEN 5000 AND 8000
ORDER BY salario DESC;
-- NOT BETWEEN: productos fuera del rango medio de precio
SELECT nombre, precio FROM productos
WHERE precio NOT BETWEEN 1000 AND 5000
ORDER BY precio;
-- IN con lista de texto: clientes de tres países
SELECT empresa, pais FROM clientes
WHERE pais IN ('Perú', 'Chile', 'Argentina')
ORDER BY empresa;
-- NOT IN: pedidos que no están ni cancelados ni pendientes
SELECT id, estado FROM pedidos
WHERE estado NOT IN ('Cancelado', 'Pendiente')
ORDER BY id;
-- BETWEEN con fechas: clientes dados de alta en 2022
SELECT empresa, fecha_alta FROM clientes
WHERE fecha_alta BETWEEN '2022-01-01' AND '2022-12-31'
ORDER BY fecha_alta;
-- IN con subconsulta: clientes que tienen algún pedido cancelado
SELECT empresa FROM clientes
WHERE id IN (SELECT cliente_id FROM pedidos WHERE estado = 'Cancelado')
ORDER BY empresa;
💡 Si unNOT IN"no devuelve nada" inesperadamente, sospecha de unNULLen la lista o subconsulta. AñadeWHERE columna IS NOT NULLa la subconsulta o reescríbelo conNOT EXISTS.
| Expresión | Equivale a |
|---|---|
x BETWEEN a AND b | x >= a AND x <= b (ambos incluidos) |
x NOT BETWEEN a AND b | x < a OR x > b |
x IN (a, b, c) | x = a OR x = b OR x = c |
x NOT IN (a, b, c) | x <> a AND x <> b AND x <> c |
x IN (SELECT ...) | coincide con un valor de la subconsulta |
⚠️ x NOT IN (.., NULL) | siempre 0 filas (trampa del NULL) |
---
← Operadores lógicos: AND, OR, NOTBúsqueda de texto: LIKE y patrones →