La cláusula WHERE

Es muy habitual tener que seleccionar datos que cumplan una condición determinada. Para ello, la sentencia SELECT cuenta con la cláusula WHERE, seguida de las condiciones que limitan las filas. Si un registro cumple la condición, entra en el resultado; si no, se descarta.

Estructura general de una consulta con la cláusula WHERE

MySQL 8.4
SELECT [DISTINCT] campos_tabla FROM nombre_tabla
WHERE condicion [operador_logico condicion] [...];
  • [ ]parte opcional
  • ...se puede repetir
DISTINCT

Elimina del resultado las filas repetidas.

Palabra claveOpcional
campos_tabla

Las columnas que aparecerán en el resultado, o * para todas las columnas.

nombre_tabla
La tabla de la que se seleccionan las filas.
condicion

Una comprobación que se hace para cada fila, por ejemplo price > 100. En el resultado solo entran las filas para las que la condición es verdadera.

operador_logico

Une varias condiciones: por ejemplo, con AND deben cumplirse las dos y con OR basta con una.

Opcional

Por ejemplo, una consulta con la cláusula WHERE puede tener este aspecto:

MySQL 8.4
SELECT * FROM Student
WHERE first_name = "Grigorij" AND YEAR(birthday) > 2000;
MySQL 8.4
SELECT * FROM Student
WHERE first_name = 'Grigorij' AND EXTRACT(YEAR FROM birthday) > 2000;
idfirst_namemiddle_namelast_namebirthdayaddress
33GrigorijGennadevichKapustin2001-12-13T00:00:00.000Zul. Pervomajskaya, d. 45, kv. 6
65GrigorijKirillovichKolobov2003-07-17T00:00:00.000Zul. CHernova, d. 9, kv. 34

En este ejemplo usamos dos condiciones a la vez:

  • first_name = "Grigorij": el nombre del estudiante debe ser «Grigorij»
  • YEAR(birthday) > 2000: el año de nacimiento es posterior a 2000
  • first_name = 'Grigorij': el nombre del estudiante debe ser «Grigorij»
  • EXTRACT(YEAR FROM birthday) > 2000: el año de nacimiento es posterior a 2000

Entre ellas está el operador lógico AND, que exige que ambas condiciones se cumplan a la vez. Como resultado, obtenemos solo los estudiantes que cumplen los dos criterios.

Operadores de comparación

Para comparar valores en SQL se usan operadores especiales. Con ellos compruebas si dos valores son iguales, si uno es mayor que otro, si son distintos, etc. El resultado de una comparación puede ser:

  • true (equivale a 1)
  • false (equivale a 0)
  • NULL (si el resultado de la comparación no está definido, por ejemplo, al comparar con NULL)
OperadorSímboloDescripción
Igualdad=Si ambos valores son iguales, el resultado es 1; si no, 0
Equivalencia<=>Igual que el operador de igualdad, salvo que el resultado es 1 al comparar NULL con NULL y 0 al comparar cualquier valor con NULL
Desigualdad<> o !=Si los valores no son iguales, el resultado es 1; si no, 0
Menor que<Si un valor es menor que el otro, el resultado es 1; si no, 0
Menor o igual que<=Si un valor es menor o igual que el otro, el resultado es 1; si no, 0
Mayor que>Si un valor es mayor que el otro, el resultado es 1; si no, 0
Mayor o igual que>=Si un valor es mayor o igual que el otro, el resultado es 1; si no, 0
OperadorSímboloDescripción
Igualdad=Si ambos valores son iguales, el resultado es true; si no, false
Desigualdad<> o !=Si los valores no son iguales, el resultado es true; si no, false
Menor que<Si un valor es menor que el otro, el resultado es true; si no, false
Menor o igual que<=Si un valor es menor o igual que el otro, el resultado es true; si no, false
Mayor que>Si un valor es mayor que el otro, el resultado es true; si no, false
Mayor o igual que>=Si un valor es mayor o igual que el otro, el resultado es true; si no, false

Prueba tú mismo estos operadores en el sandbox y mira qué resultados dan:

MySQL 8.4
SELECT
    2 = 1,
	'a' = 'a',
    1 <=> NULL,
	NULL <=> NULL,
	2 <> 2,
	3 < 4,
	10 <= 10,
	7 > 1,
	8 >= 10;
2 = 1'a' = 'a'1 <=> NULLNULL <=> NULL2 <> 23 < 410 <= 107 > 18 >= 10
010101110
MySQL 8.4
SELECT
    2 = 1 AS "2 = 1",
	'a' = 'a' AS "'a' = 'a'",
	2 <> 2 AS "2 <> 2",
	3 < 4 AS "3 < 4",
	10 <= 10 AS "10 <= 10",
	7 > 1 AS "7 > 1",
	8 >= 10 AS "8 >= 10";
2 = 1'a' = 'a'2 <> 23 < 410 <= 107 > 18 >= 10
falsetruefalsetruetruetruefalse

Operadores lógicos

Los operadores lógicos te ayudan cuando necesitas combinar varias condiciones en una misma consulta SQL. Con ellos puedes seleccionar con flexibilidad solo las filas que de verdad necesitas. Veamos cómo funciona en la práctica:

  • AND: las dos condiciones deben cumplirse.

    Imagina que buscas vuelos que cumplan dos requisitos a la vez: por ejemplo, que el avión sea de un modelo concreto y que salga de una ciudad determinada. El operador AND te permite unir estas condiciones.

    MySQL 8.4
    SELECT * FROM Trip
    WHERE plane = 'Boeing' AND town_from = 'London';
    
    MySQL 8.4
    SELECT * FROM Trip
    WHERE plane = 'Boeing' AND town_from = 'London';
    
    idcompanyplanetown_fromtown_totime_outtime_in
    77715BoeingLondonSingapore1900-01-01T01:00:00.000Z1900-01-01T11:00:00.000Z
    77735BoeingLondonSingapore1900-01-01T03:00:00.000Z1900-01-01T13:00:00.000Z
    77755BoeingLondonSingapore1900-01-01T09:00:00.000Z1900-01-01T20:00:00.000Z
    77775BoeingLondonSingapore1900-01-01T18:00:00.000Z1900-01-02T06:00:00.000Z
    88815BoeingLondonParis1900-01-01T03:00:00.000Z1900-01-01T04:00:00.000Z

    Esta consulta selecciona solo los vuelos en los que el modelo de avión es Boeing y la ciudad de salida es London.

    Si no se cumple al menos una de las condiciones (por ejemplo, el avión no es un Boeing o el vuelo no sale de London), ese vuelo no entra en el resultado.

  • OR: basta con que se cumpla al menos una condición.

    El operador OR funciona como un «o». Si al menos una de las condiciones es verdadera, la fila entra en el resultado. Es útil cuando quieres ver todos los vuelos que cumplen al menos uno de tus criterios.

    MySQL 8.4
    SELECT * FROM Trip
    WHERE town_to = 'Paris' OR plane = 'Airbus';
    
    MySQL 8.4
    SELECT * FROM Trip
    WHERE town_to = 'Paris' OR plane = 'Airbus';
    
    idcompanyplanetown_fromtown_totime_outtime_in
    11004BoeingRostovParis1900-01-01T14:30:00.000Z1900-01-01T17:50:00.000Z
    88815BoeingLondonParis1900-01-01T03:00:00.000Z1900-01-01T04:00:00.000Z

    Como resultado obtendrás todos los vuelos que llegan a Paris y, además, todos los vuelos en un Airbus (aunque no vayan a Paris).

    Si un vuelo va en Airbus y además a Paris, también entra en el resultado.

  • NOT: invierte la condición.

    El operador NOT invierte la condición: si era verdadera, pasa a ser falsa, y al revés. Es útil cuando quieres excluir ciertos valores.

    MySQL 8.4
    SELECT * FROM Trip WHERE NOT town_to = 'Moscow';
    
    MySQL 8.4
    SELECT * FROM Trip WHERE NOT town_to = 'Moscow';
    

    Esta consulta selecciona todos los vuelos que no llegan a Moscow.

    Es decir, si la ciudad de llegada es Moscow, ese vuelo no entra en el resultado. Todos los demás, sí.

  • XOR: un operador que te ayuda a seleccionar las filas en las que se cumple solo una de las dos condiciones, pero no ambas a la vez.

    Supongamos que quieres encontrar los vuelos que o bien salen de Moscow, o bien llegan a Paris, pero no ambas cosas a la vez. Veamos todos los casos posibles:

    Sale
    de Moscow
    Llega
    a Paris
    Entra
    en el resultado
    Explicación
    SíNo✅ SíSolo se cumple la primera condición
    NoSí✅ SíSolo se cumple la segunda condición
    SíSí❌ NoSe cumplen las dos condiciones: XOR excluye estos casos
    NoNo❌ NoNo se cumple ninguna condición
    MySQL 8.4
    SELECT * FROM trip
    WHERE town_from = 'Moscow' XOR town_to = 'Paris';
    
    MySQL 8.4
    SELECT * FROM trip
    WHERE (town_from = 'Moscow' AND town_to != 'Paris')
       OR (town_from != 'Moscow' AND town_to = 'Paris');
    

Prioridad de los operadores lógicos

Cuando escribes una consulta con varias condiciones, SQL tiene que decidir en qué orden comprobarlas. Es como en matemáticas: primero la multiplicación y luego la suma. Los operadores lógicos de SQL también tienen su propio orden, que se llama prioridad.

  • Primero, NOT
  • Después, AND
  • Luego, XOR
  • Por último, OR

¿Por qué es importante?

Puede parecer que las condiciones se comprueban simplemente de izquierda a derecha, ¡pero no es así! Si no tienes en cuenta el orden, puedes obtener un resultado inesperado.

Fíjate en este ejemplo:

MySQL 8.4
SELECT *
FROM Trip
WHERE town_to = 'Paris'
	OR plane = 'Boeing'
	AND NOT town_from = 'Moscow';
MySQL 8.4
SELECT *
FROM Trip
WHERE town_to = 'Paris'
	OR plane = 'Boeing'
	AND NOT town_from = 'Moscow';
idcompanyplanetown_fromtown_totime_outtime_in
11004BoeingRostovParis1900-01-01T14:30:00.000Z1900-01-01T17:50:00.000Z
11014BoeingParisRostov1900-01-01T08:12:00.000Z1900-01-01T11:45:00.000Z
77715BoeingLondonSingapore1900-01-01T01:00:00.000Z1900-01-01T11:00:00.000Z
77725BoeingSingaporeLondon1900-01-01T12:00:00.000Z1900-01-02T02:00:00.000Z
77735BoeingLondonSingapore1900-01-01T03:00:00.000Z1900-01-01T13:00:00.000Z
77745BoeingSingaporeLondon1900-01-01T14:00:00.000Z1900-01-02T06:00:00.000Z
77755BoeingLondonSingapore1900-01-01T09:00:00.000Z1900-01-01T20:00:00.000Z
77765BoeingSingaporeLondon1900-01-01T18:00:00.000Z1900-01-02T08:00:00.000Z
77775BoeingLondonSingapore1900-01-01T18:00:00.000Z1900-01-02T06:00:00.000Z
77785BoeingSingaporeLondon1900-01-01T22:00:00.000Z1900-01-02T12:00:00.000Z
88815BoeingLondonParis1900-01-01T03:00:00.000Z1900-01-01T04:00:00.000Z
88825BoeingParisLondon1900-01-01T22:00:00.000Z1900-01-01T23:00:00.000Z

Esto es lo que ocurre:

  • Primero se comprueba que el vuelo no salga de Moscow (NOT town_from = 'Moscow').

  • Después se mira que el avión sea un Boeing y se une con la primera condición mediante AND; es decir, se buscan los vuelos que no salen de Moscow y van en Boeing (plane = 'Boeing' AND NOT town_from = 'Moscow').

  • Luego se añaden al resultado todos los vuelos que llegan a Paris, aunque no vayan en Boeing y salgan de Moscow (town_to = 'Paris' OR ...).

Al final se obtiene esta selección:

  • Todos los vuelos que no salen de Moscow y van en Boeing
  • Y, además, todos los vuelos que llegan a Paris

Si quieres cambiar el orden en que se comprueban las condiciones o hacerlo más claro, usa paréntesis. Todo lo que está entre paréntesis se evalúa primero. Por ejemplo, si colocas los paréntesis a mano según la prioridad de los operadores lógicos, ¡enseguida se ve cómo se ejecutará la consulta!

MySQL 8.4
SELECT *
FROM Trip
WHERE (
		town_to = 'Paris'
		OR (
			plane = 'Boeing'
			AND (NOT town_from = 'Moscow')
		)
	);
MySQL 8.4
SELECT *
FROM Trip
WHERE (
		town_to = 'Paris'
		OR (
			plane = 'Boeing'
			AND (NOT town_from = 'Moscow')
		)
	);

Y ahora pruébalo tú: supongamos que quieres obtener la lista de vuelos que salen de Paris o van en un Boeing, y que no vuelan a Moscow. Puedes conseguirlo colocando bien los paréntesis en la consulta original del ejemplo. ¿Cómo lo harías?