WHERE: Filtrar datos con condiciones

Lectura
20 min~8 min lectura
CONCEPTO CLAVE: La cláusula WHERE es el filtro essential de SQL. Sin ella, cada consulta devolvería TODOS los registros de una tabla. Con WHERE, puedes especificar exactamente qué filas necesitas, transformando una tabla completa en información útil y precisa.

¿Qué es la cláusula WHERE?

Imagina que tienes una biblioteca con miles de libros. Si alguien te preguntara "¿qué libros tenemos?", tendrías que listar todos. Pero si te preguntaran "¿qué libros de ciencia ficción tenemos escritos después del año 2000?", usarías un filtro para mostrar solo los relevantes. En SQL, ese filtro se llama WHERE.

La sintaxis básica es:

SELECT columna1, columna2
FROM nombre_tabla
WHERE condición;

La condición es una expresión lógica que cada fila debe cumplir para ser incluida en el resultado. Solo las filas donde la condición sea verdadera (TRUE) aparecerán.

Operadores de comparación

Los operadores de comparación son el corazón de WHERE. Permiten comparar valores y determinar si una fila cumple o no con nuestro criterio.

OperadorDescripciónEjemplo
=Igual aciudad = 'Madrid'
<>Diferente deestado <> 'inactivo'
<Menor queedad < 18
>Mayor queprecio > 100
<=Menor o igual questock <= 10
>=Mayor o igual queventas >= 1000

Ejemplos prácticos con operadores

Usando una tabla de ejemplo empleados con columnas: id, nombre, departamento, salario, fecha_contratacion

-- Encontrar empleados del departamento de Ventas
SELECT nombre, salario
FROM empleados
WHERE departamento = 'Ventas';

-- Empleados con salario mayor a 3000
SELECT nombre, departamento
FROM empleados
WHERE salario > 3000;

-- Empleados contratados antes de 2020
SELECT nombre, fecha_contratacion
FROM empleados
WHERE fecha_contratacion < '2020-01-01';
📌 Recuerda: Los valores de texto (strings) deben ir entre comillas simples. Las fechas también van entre comillas simples en formato 'YYYY-MM-DD'.

Múltiples condiciones: AND y OR

La vida real rara vez tiene condiciones únicas. Usually, necesitas combinar varios criterios. Para esto, SQL ofrece dos operadores lógicos fundamentales:

  • AND: Todas las condiciones deben ser verdaderas
  • OR: Al menos una condición debe ser verdadera

Uso de AND

-- Empleados de Ventas con salario mayor a 2500
SELECT nombre, departamento, salario
FROM empleados
WHERE departamento = 'Ventas' AND salario > 2500;

Uso de OR

-- Empleados del departamento de RRHH o de Marketing
SELECT nombre, departamento
FROM empleados
WHERE departamento = 'RRHH' OR departamento = 'Marketing';

Combinando AND y OR

Cuando combines ambos, usa paréntesis para controlar el orden de evaluación:

-- Empleados senior de Ventas (salario > 4000) O cualquier empleado de RRHH
SELECT nombre, departamento, salario
FROM empleados
WHERE (departamento = 'Ventas' AND salario > 4000)
   OR departamento = 'RRHH';
⚠️ Precaución: Sin paréntesis, SQL evalúa AND antes que OR. Esto puede generar resultados inesperados. Siempre usa paréntesis cuando combines ambos operadores para garantizar el comportamiento deseado.

El operador LIKE: Búsquedas con patrones

¿Y si quieres encontrar todos los clientes cuyos nombres empiezan con "Mar"? ¿O todos los productos que contienen "azul" en su descripción? Para esto existe LIKE con dos comodines fundamentales:

ComodínSignificadoEjemplo
%Cualquier secuencia de caracteres'Mar%' = cualquier texto que empiece con Mar
_Un solo carácter'Jo_n' = Juan, John, Jon
-- Clientes cuyo nombre empieza con 'Mar'
SELECT nombre, email
FROM clientes
WHERE nombre LIKE 'Mar%';

-- Productos con 'azul' en cualquier posición
SELECT nombre_producto, descripcion
FROM productos
WHERE descripcion LIKE '%azul%';

-- Códigos que sigan el patrón: dos letras, un número, dos letras
SELECT codigo, descripcion
FROM inventario
WHERE codigo LIKE '__1__';
💡 Consejo: LIKE es útil para búsquedas flexibles, pero es más lento que comparaciones exactas (=). En tablas muy grandes, considera usar índices o búsqueda de texto completo si el rendimiento es crítico.

El operador IN: Múltiples valores posibles

Cuando necesitas verificar si un valor está en una lista de opciones, IN hace el código más limpio y legible:

-- Empleados de tres departamentos específicos (versión larga con OR)
SELECT nombre, departamento
FROM empleados
WHERE departamento = 'Ventas' 
   OR departamento = 'Marketing' 
   OR departamento = 'Comercial';

-- Misma consulta con IN (más elegante)
SELECT nombre, departamento
FROM empleados
WHERE departamento IN ('Ventas', 'Marketing', 'Comercial');

IN también acepta subconsultas, lo que permite comparaciones dinámicas:

-- Productos de categorías que tienen más de 100 unidades en stock
SELECT nombre_producto, categoria
FROM productos
WHERE categoria IN (
    SELECT categoria
    FROM inventario
    WHERE cantidad > 100
);

El operador BETWEEN: Rangos inclusivos

Para rangos numéricos o de fechas, BETWEEN ofrece una sintaxis elegante:

-- Empleados con salario entre 2000 y 5000 (incluye ambos extremos)
SELECT nombre, salario
FROM empleados
WHERE salario BETWEEN 2000 AND 5000;

-- Pedidos realizados en el primer trimestre de 2024
SELECT numero_pedido, fecha_pedido, total
FROM pedidos
WHERE fecha_pedido BETWEEN '2024-01-01' AND '2024-03-31';

-- Equivale a:
SELECT numero_pedido, fecha_pedido, total
FROM pedidos
WHERE fecha_pedido >= '2024-01-01' 
  AND fecha_pedido <= '2024-03-31';
📌 Nota importante: BETWEEN es inclusivo, es decir, incluye tanto el valor inicial como el final. '2024-01-01' y '2024-03-31' estarán en los resultados si existen registros con esas fechas.

Manejo de valores nulos: IS NULL

Los valores nulos representan datos desconocidos o faltantes. No deben confundirse con cadenas vacías o ceros. Para verificar si un valor es nulo, se usa IS NULL (nunca = NULL):

-- Clientes sin número de teléfono registrado
SELECT nombre, email, telefono
FROM clientes
WHERE telefono IS NULL;

-- Empleados que SÍ tienen fecha de finalización de contrato
SELECT nombre, fecha_fin_contrato
FROM empleados
WHERE fecha_fin_contrato IS NOT NULL;
⚠️ Error común: Nunca escribas WHERE telefono = NULL. Esto siempre devolverá falso porque NULL no es igual a nada, ni siquiera a otro NULL. La sintaxis correcta es WHERE telefono IS NULL.

Negación: NOT

El operador NOT invierte cualquier condición. Es útil para exclude datos no deseados:

-- Todos los productos EXCEPTO los de la categoría Electrónica
SELECT nombre, categoria, precio
FROM productos
WHERE NOT categoria = 'Electrónica';

-- Equivale a:
SELECT nombre, categoria, precio
FROM productos
WHERE categoria <> 'Electrónica';

-- Combinando NOT con otras condiciones
-- Empleados de Ventas que NO ganan más de 5000
SELECT nombre, departamento, salario
FROM empleados
WHERE departamento = 'Ventas' 
  AND NOT salario > 5000;

Orden de evaluación y paréntesis

SQL evalúa las condiciones en un orden específico:

  1. Primero: Comparaciones (=, <, >, LIKE, IN, BETWEEN)
  2. Segundo: NOT
  3. Tercero: AND
  4. Cuarto: OR
-- Sin paréntesis: SQL evalúa AND primero
-- Esto encuentra: (Marketing con ventas > 1000) O (cualquiera de RRHH)
SELECT nombre, departamento, ventas
FROM empleados
WHERE departamento = 'Marketing' AND ventas > 1000
   OR departamento = 'RRHH';

-- Con paréntesis: SQL evalúa el OR primero
-- Esto encuentra: Marketing O RRHH, y además deben tener ventas > 1000
SELECT nombre, departamento, ventas
FROM empleados
WHERE (departamento = 'Marketing' OR departamento = 'RRHH')
  AND ventas > 1000;
Ver más: Ejemplo completo integrando todo

Vamos a crear una consulta compleja que combine todo lo aprendido:

-- Encuentra todos los pedidos que cumplan TODOS estos criterios:
-- 1. Sean del año 2023 o posterior
-- 2. El cliente NO sea de la ciudad de 'Lima'
-- 3. El total esté entre 100 y 5000 (inclusive)
-- 4. El estado sea 'Completado' o 'Enviado'
-- 5. El cliente tenga email registrado (no nulo)

SELECT 
    p.numero_pedido,
    p.fecha_pedido,
    p.total,
    p.estado,
    c.nombre AS cliente,
    c.ciudad
FROM pedidos p
JOIN clientes c ON p.cliente_id = c.id
WHERE p.fecha_pedido >= '2023-01-01'
  AND c.ciudad <> 'Lima'
  AND p.total BETWEEN 100 AND 5000
  AND p.estado IN ('Completado', 'Enviado')
  AND c.email IS NOT NULL
ORDER BY p.fecha_pedido DESC;

Buenas prácticas con WHERE

  • Especificidad primero: Filtra lo más restrictivo primero para reducir el conjunto de datos temprano.
  • Usa índices: Si filtras frecuentemente una columna, asegúrate de que tenga un índice.
  • Evita funciones en columnas filtradas: WHERE YEAR(fecha) = 2024 es más lento que WHERE fecha >= '2024-01-01' AND fecha < '2025-01-01'.
  • Comenta tu código: Las consultas complejas merecen explicaciones.
💡 Refactorización progresiva: Cuando construyas consultas complejas, comienza simple y añade condiciones una por una. Después de cada adición, verifica que los resultados sean los esperados. Esto hace la depuración mucho más sencilla.

Errores frecuentes y cómo evitarlos

ErrorProblemaSolución
WHERE nombre = JuanSin comillas en textoWHERE nombre = 'Juan'
WHERE fecha = NULLComparando con NULLWHERE fecha IS NULL
WHERE x > 10 AND y > 5 OR z > 3Sin paréntesis clarosWHERE (x > 10 AND y > 5) OR z > 3
WHERE nombre LIKE '%Juan'Confundiendo posición del %LIKE '%Juan%' para encontrar en cualquier parte
"La diferencia entre una consulta que tarda 0.01 segundos y una que tarda 30 segundos a menudo está en cómo escribimos las condiciones WHERE. Un buen filtrado es la base del rendimiento SQL."
🧠 Quiz: ¿Qué aprendiste sobre WHERE?

¿Cuál de las siguientes consultas devolverá todos los clientes cuyo nombre empiece con "Ana"?

  • A) SELECT * FROM clientes WHERE nombre LIKE '%Ana';
  • B) SELECT * FROM clientes WHERE nombre LIKE 'Ana%';
  • C) SELECT * FROM clientes WHERE nombre = 'Ana%';
  • D) SELECT * FROM clientes WHERE nombre LIKE 'Ana_';
✅ Respuesta correcta: B) LIKE 'Ana%' usa el comodín % después de 'Ana', lo que significa "cualquier texto que comience con Ana". La opción A buscaría nombres que terminen con Ana. La C usa comillas literales (buscaría exactamente 'Ana%'). La D usa _ que solo coincide con un carácter.
🧠 Quiz 2

¿Qué consulta muestra los productos con precio entre 50 y 200 euros, excluyendo la categoría 'Ofertas'?

  • A) WHERE precio >= 50 AND precio <= 200 AND categoria <> 'Ofertas'
  • B) WHERE precio BETWEEN 50 AND 200 OR categoria = 'Ofertas'
  • C) WHERE NOT precio BETWEEN 50 AND 200 AND categoria = 'Ofertas'
  • D) WHERE categoria NOT IN 'Ofertas' AND precio BETWEEN 50 AND 200
✅ Respuesta correcta: A) Usa BETWEEN para el rango y <> (diferente de) para excluir 'Ofertas'. La B incluiría ofertas por el OR. La C es casi lo opuesto. La D tiene sintaxis incorrecta (falta paréntesis en NOT IN).

Resumen

La cláusula WHERE es tu herramienta principal para filtrar datos en SQL. Dominar sus operadores y combinadores te permitirá:

  • Extraer exactamente los datos que necesitas
  • Crear consultas eficientes y legibles
  • Combinar múltiples condiciones lógicas
  • Buscar patrones de texto con LIKE
  • Manejar valores nulos correctamente

En la siguiente lección, aprenderemos a ordenar y limitar resultados con ORDER BY y LIMIT, complementando perfectamente tus habilidades de filtrado.