Saltar al contenido
where.sql · devschool

WHERE en SQL

Lección 3 de 22 · 11 min de lectura · Actualizado el

En esta lección
  1. Comparaciones
  2. Varias condiciones: AND, OR, NOT
  3. IN y NOT IN: el valor está en una lista
  4. BETWEEN y NOT BETWEEN: rangos
  5. Filtrar fechas
  6. Buscar texto: LIKE
  7. Valores vacíos: IS NULL
  8. Errores frecuentes
  9. Resumen

WHERE filtra las filas: solo aparecen las que cumplen la condición. Es lo que convierte “dame todos los clientes” en “dame los clientes de Santander mayores de edad”. Lo usarás en casi todas las consultas, y también en UPDATE y DELETE para decidir qué filas se cambian o se borran. En esta lección verás los operadores de comparación, cómo combinar condiciones, los atajos IN y BETWEEN, cómo filtrar fechas y cómo buscar texto con LIKE.

SELECT nombre, edad
FROM clientes
WHERE ciudad = 'Santander';
nombreedad
Ana García34
Marta Ruiz45

La base de datos recorre las filas de clientes y, para cada una, evalúa la condición. Si es verdadera, la fila pasa al resultado; si no, se descarta.

Comparaciones

OperadorSignificadoEjemplo
=Igual (un solo =, no ==)edad = 22
<> o !=Distintociudad <> 'Madrid'
> / <Mayor / menoredad > 30
>= / <=Mayor o igual / menor o igualimporte >= 45
SELECT id, fecha, importe
FROM pedidos
WHERE importe >= 45;
idfechaimporte
12026-09-0145.00
22026-09-03120.50
42026-09-1260.00

Los textos y las fechas van entre comillas simples; los números, sin comillas. <> es el operador estándar para “distinto”; != funciona en todos los sistemas habituales, pero <> es el que verás en la documentación.

Varias condiciones: AND, OR, NOT

  • AND: se tienen que cumplir las dos condiciones.
  • OR: basta con que se cumpla una.
  • NOT: invierte la condición.
-- Clientes de Madrid mayores de edad
SELECT nombre FROM clientes
WHERE ciudad = 'Madrid' AND edad >= 18;
nombre
Eva Martín
-- Clientes de Bilbao o de Madrid
SELECT nombre FROM clientes
WHERE ciudad = 'Bilbao' OR ciudad = 'Madrid';
nombre
Luis Pérez
Pablo Díaz
Eva Martín
-- Clientes que no son de Madrid
SELECT nombre FROM clientes
WHERE NOT ciudad = 'Madrid';
nombre
Ana García
Luis Pérez
Marta Ruiz

Precedencia: AND va antes que OR

Igual que en matemáticas la multiplicación va antes que la suma, en SQL AND se evalúa antes que OR. Si los mezclas sin paréntesis, el resultado puede no ser el que esperas.

Queremos los clientes de Bilbao o Madrid que tengan 25 años o más:

-- ✗ Mal: sin paréntesis
SELECT nombre, ciudad, edad FROM clientes
WHERE ciudad = 'Bilbao' OR ciudad = 'Madrid' AND edad >= 25;
nombreciudadedad
Luis PérezBilbao22
Eva MartínMadrid29

¡Luis tiene 22 años y aparece! La base de datos lo ha leído así: ciudad = 'Bilbao' OR (ciudad = 'Madrid' AND edad >= 25). Es decir, cualquier cliente de Bilbao, o los de Madrid de 25 o más. Con paréntesis dices lo que de verdad quieres:

-- ✓ Bien
SELECT nombre, ciudad, edad FROM clientes
WHERE (ciudad = 'Bilbao' OR ciudad = 'Madrid') AND edad >= 25;
nombreciudadedad
Eva MartínMadrid29

Consejo: siempre que mezcles AND y OR, pon paréntesis, aunque sepas la regla de precedencia. Quien lea la consulta (incluido tú dentro de un mes) no tendrá que pensarlo.

IN y NOT IN: el valor está en una lista

IN es un atajo para varios OR sobre la misma columna:

WHERE ciudad IN ('Bilbao', 'Madrid')   -- igual que los dos OR de antes

Y NOT IN busca lo contrario, los valores que no están en la lista:

SELECT nombre, ciudad FROM clientes
WHERE ciudad NOT IN ('Bilbao', 'Madrid');
nombreciudad
Ana GarcíaSantander
Marta RuizSantander

La lista también puede salir de otra consulta, como verás en subconsultas.

Cuidado: si la lista de un NOT IN contiene un NULL, la consulta no devuelve ninguna fila. Lo explicamos en valores NULL.

BETWEEN y NOT BETWEEN: rangos

BETWEEN a AND b comprueba si el valor está entre a y b, incluidos los dos extremos. Es lo mismo que >= a AND <= b:

SELECT id, importe FROM pedidos
WHERE importe BETWEEN 30 AND 60;
idimporte
145.00
460.00
533.25

El pedido 4, de 60.00 exactos, entra porque el extremo está incluido. NOT BETWEEN devuelve lo que queda fuera del rango:

SELECT id, importe FROM pedidos
WHERE importe NOT BETWEEN 30 AND 60;
idimporte
2120.50
312.99

El valor pequeño va siempre primero: BETWEEN 60 AND 30 no devuelve nada.

Cuidado: con textos, BETWEEN compara alfabéticamente. nombre BETWEEN 'A' AND 'M' no incluye a Marta Ruiz, porque 'Marta Ruiz' va después de 'M' en el orden alfabético (igual que “Ma” va después de “M” en un diccionario). Para “nombres que empiezan de la A a la M”, usa nombre < 'N'.

Filtrar fechas

Las fechas se escriben como texto entre comillas simples con el formato 'AAAA-MM-DD' (año, mes, día). Es el formato estándar y el único que todas las bases de datos entienden igual. Con él puedes usar los operadores de siempre:

-- Pedidos desde el 10 de septiembre
SELECT id, fecha FROM pedidos
WHERE fecha >= '2026-09-10';
idfecha
32026-09-10
42026-09-12
52026-09-15
-- Pedidos de la primera decena de septiembre
SELECT id, fecha, importe FROM pedidos
WHERE fecha BETWEEN '2026-09-01' AND '2026-09-10';
idfechaimporte
12026-09-0145.00
22026-09-03120.50
32026-09-1012.99

Cuidado: si la columna es de tipo DATETIME (fecha y hora), '2026-09-10' significa “10 de septiembre a las 00:00:00”. Un pedido del día 10 a las 18:30 quedaría fuera del BETWEEN. Para rangos de días con hora, usa >= el primer día y < el día siguiente: WHERE fecha >= '2026-09-01' AND fecha < '2026-09-11'.

Para filtrar por año o por mes existen funciones como YEAR(fecha) en MySQL. Las verás en funciones de texto, números y fechas.

Buscar texto: LIKE

= solo encuentra textos idénticos. Para buscar partes de un texto se usa LIKE con un patrón que admite dos comodines:

ComodínSignificaEjemploEncaja con
%Cualquier cantidad de caracteres, incluso ninguno'M%'Marta, Madrid, M
_Exactamente un carácter'_u%'Luis, Just (segunda letra “u”)
WHERE nombre LIKE 'M%'       -- empieza por M → Marta Ruiz
WHERE nombre LIKE '%ez'      -- termina en "ez" → Luis Pérez
WHERE nombre LIKE '%ar%'     -- contiene "ar" → Ana García, Marta Ruiz, Eva Martín
WHERE nombre LIKE '_u%'      -- la segunda letra es "u" → Luis Pérez

Puedes combinar los dos comodines. Este patrón busca nombres cuyo apellido tiene exactamente cuatro letras (un espacio y cuatro caracteres al final):

SELECT nombre FROM clientes
WHERE nombre LIKE '% ____';
nombre
Marta Ruiz
Pablo Díaz

Y NOT LIKE devuelve lo que no encaja con el patrón:

SELECT nombre FROM clientes
WHERE nombre NOT LIKE '%a%';
nombre
Luis Pérez

Sin comodines, LIKE 'Madrid' equivale a = 'Madrid'. Si no necesitas patrón, usa =, que es más claro y más rápido.

Buscar un % o un _ de verdad: ESCAPE

¿Y si el texto que buscas contiene un % o un _? Imagina una tabla de códigos de descuento:

CREATE TABLE descuentos (codigo VARCHAR(20), descripcion VARCHAR(50));
INSERT INTO descuentos VALUES
  ('VERANO_10', '10 % en verano'),
  ('VERANOX10', 'Prueba'),
  ('BIENVENIDA', '5 % primera compra'),
  ('VIP_20', '20 % clientes VIP');

SELECT codigo FROM descuentos
WHERE codigo LIKE '%_10';
codigo
VERANO_10
VERANOX10

Sobra VERANOX10: el _ del patrón es un comodín y encaja con la X. Para que un comodín cuente como carácter normal, se escapa: eliges un carácter de escape con ESCAPE y lo pones delante.

SELECT codigo FROM descuentos
WHERE codigo LIKE '%!_10' ESCAPE '!';
codigo
VERANO_10

Ahora !_ significa “un guion bajo de verdad”. Lo mismo con el porcentaje: descripcion LIKE '%!%%' ESCAPE '!' busca descripciones que contienen un %.

Nota: en MySQL y PostgreSQL, la barra invertida \ ya es el carácter de escape por defecto (LIKE '%\_10'), pero en SQLite no. Con ESCAPE funciona igual en todos.

Mayúsculas y minúsculas

¿Encuentra LIKE 'm%' a Marta? Depende del sistema:

Sistemanombre LIKE 'm%'Cómo buscar sin distinguir
MySQL / MariaDBEncuentra a Marta (con la configuración habitual, no distingue)Ya lo hace
PostgreSQLNo la encuentra (distingue)ILIKE 'm%' o LOWER(nombre) LIKE 'm%'
SQLiteLa encuentra (no distingue en letras sin tilde)Ya lo hace

En MySQL, además, la configuración habitual tampoco distingue tildes: LIKE '%perez%' encuentra a “Luis Pérez”. En PostgreSQL y SQLite, no. La forma portable de buscar sin distinguir mayúsculas es pasar las dos partes a minúsculas: WHERE LOWER(nombre) LIKE '%marta%'.

Consejo: un patrón que empieza por % ('%ez') obliga a la base de datos a revisar todas las filas, porque no puede usar un índice. En tablas grandes se nota. 'M%' sí puede aprovecharlo.

Valores vacíos: IS NULL

NULL significa “sin valor, desconocido”. No se puede comparar con =; hay que usar IS NULL o IS NOT NULL:

SELECT nombre FROM clientes WHERE ciudad IS NULL;      -- ✓
SELECT nombre FROM clientes WHERE ciudad = NULL;       -- ✗ nunca devuelve nada

Es un tema con bastantes trampas, así que tiene su propia lección: valores NULL.

Errores frecuentes

  • Mezclar AND y OR sin paréntesis, como en el ejemplo de Luis.
  • Escribir == en lugar de =: en SQL la comparación lleva un solo igual.
  • Olvidar las comillas en un texto: WHERE ciudad = Madrid hace que la base de datos busque una columna llamada Madrid.
  • Repetir la columna mal en un OR: WHERE ciudad = 'Bilbao' OR 'Madrid' no da error en MySQL, pero no hace lo que crees. Escribe ciudad = ... OR ciudad = ... o usa IN.

Resumen

Quieres…Escribe
Un valor exactoWHERE ciudad = 'Madrid'
Distinto deWHERE ciudad <> 'Madrid'
Varias condiciones a la vezWHERE a AND b
Una u otraWHERE (a OR b) con paréntesis si hay AND
En una lista / fuera de ellaIN ('Bilbao', 'Madrid') / NOT IN (...)
En un rango (extremos incluidos)BETWEEN 30 AND 60 / NOT BETWEEN
Fechasfecha >= '2026-09-10'
Empieza, termina o contieneLIKE 'M%', LIKE '%ez', LIKE '%ar%'
Un carácter cualquieraLIKE '_u%'
Un _ o % literalLIKE '%!_10' ESCAPE '!'
Sin valorIS NULL / IS NOT NULL

En la siguiente lección profundizarás en los valores NULL.

Pon a prueba lo que has aprendido

[SQL] ¿Qué palabra filtra las filas de una consulta?

[SQL] ¿Qué clientes devuelve la consulta?
SELECT nombre FROM clientes
WHERE ciudad = 'Santander' AND edad >= 18;

[SQL] ¿Qué comprueba mejor si un campo está vacío (sin valor)?

[SQL] Con la tabla clientes del curso, ¿qué nombres devuelve esta consulta?
SELECT nombre FROM clientes
WHERE ciudad = 'Bilbao' OR ciudad = 'Madrid' AND edad >= 25;

[SQL] ¿Qué patrón encuentra el código 'VERANO_10' pero no 'VERANOX10'?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.