Lógica condicional: la expresión CASE

SQL, como muchos lenguajes de programación, te permite escribir lógica condicional para devolver uno de varios valores posibles en función de un conjunto de condiciones. En este artículo veremos cómo se hace en SQL con la expresión CASE.

¿Qué es la lógica condicional?

La lógica condicional significa que un programa tiene varios caminos de ejecución según se cumplan unas u otras condiciones.

Por ejemplo, en la base de datos «Schedule» hay una tabla Student con la columna birthday, que guarda la fecha de nacimiento del estudiante. Supongamos que en el resultado no queremos mostrar la fecha de nacimiento en sí, sino el texto «Mayor de edad» o «Menor de edad», según si el estudiante ya ha cumplido 18 años. Esto es un ejemplo de lógica condicional: se debe mostrar un valor u otro en función de una condición concreta.

Una consulta así con CASE podría tener este aspecto:

MySQL 8.4
SELECT first_name, last_name,
CASE
  WHEN TIMESTAMPDIFF(YEAR, birthday, NOW()) >= 18 THEN 'Mayor de edad'
  ELSE 'Menor de edad'
END AS status
FROM Student
MySQL 8.4
SELECT first_name, last_name,
CASE
  WHEN EXTRACT(YEAR FROM AGE(NOW(), birthday)) >= 18 THEN 'Mayor de edad'
  ELSE 'Menor de edad'
END AS status
FROM Student
first_namelast_namestatus
NikolajSokolovMayor de edad
VyacheslavEliseevMayor de edad
IvanEfremovMayor de edad
AnatolijZHdanovMenor de edad
GeorgijNoskovMayor de edad
ArtyomSergeevMenor de edad
ArinaEvseevaMayor de edad
AngelinaVoroncovaMayor de edad
EkaterinaUstinovaMayor de edad
RaisaLapinaMayor de edad
LeonidIgnatovMenor de edad
SnezhanaSeliverstovaMayor de edad
SemyonBiryukovMayor de edad
GeorgijBaranovMayor de edad
YUliyaVishnyakovaMayor de edad
ValentinaBolshakovaMayor de edad
LeonidKryukovMayor de edad
VladislavCvetkovMayor de edad
SnezhanaMorozovaMayor de edad
LyubovBorisovaMayor de edad
AnfisaKalashnikovaMayor de edad
AnnaOsipovaMayor de edad

Sintaxis de la expresión CASE de búsqueda

MySQL 8.4
CASE
    WHEN condicion THEN resultado
    [WHEN ...]
    [ELSE resultado_por_defecto]
END
  • [ ]parte opcional
  • ...se puede repetir
condicion
Expresión lógica de la rama WHEN, por ejemplo price > 100.
resultado

El valor que devolverá CASE si la condición de la rama es verdadera.

resultado_por_defecto

El valor para el caso en que no se cumpla ninguna condición. Sin ELSE se devuelve NULL.

Opcional

Las ramas WHEN se comprueban por orden: si la condicion de la primera rama es verdadera, la expresión CASE devuelve su resultado; si no, se comprueba la siguiente rama, y así sucesivamente.

Ejemplo

Veamos la expresión CASE con un ejemplo: determinar la etapa educativa de cada curso escolar.

Etapas de la educación escolar

MySQL 8.4
SELECT name,
CASE
  WHEN SUBSTRING(name, 1, INSTR(name, ' ')) IN (10, 11) THEN 'Bachillerato'
  WHEN SUBSTRING(name, 1, INSTR(name, ' ')) IN (5, 6, 7, 8, 9) THEN 'Secundaria'
  ELSE 'Primaria'
END AS stage
FROM Class
MySQL 8.4
SELECT name,
CASE
  WHEN SUBSTRING(name, 1, POSITION(' ' IN name) - 1) IN ('10', '11') THEN 'Bachillerato'
  WHEN SUBSTRING(name, 1, POSITION(' ' IN name) - 1) IN ('5', '6', '7', '8', '9') THEN 'Secundaria'
  ELSE 'Primaria'
END AS stage
FROM Class
namestage
8 ASecundaria
8 BSecundaria
9 CSecundaria
9 BSecundaria
9 ASecundaria
10 BBachillerato
10 ABachillerato
11 BBachillerato
11 ABachillerato
7 ASecundaria
7 BSecundaria
6 ASecundaria
6 BSecundaria
5 ASecundaria
5 BSecundaria
4 APrimaria
  • Primero extraemos el número del curso a partir de su nombre:
    MySQL 8.4
    SUBSTRING(name, 1, INSTR(name, ' '))
    
  • Primero extraemos el número del curso a partir de su nombre:
    MySQL 8.4
    SUBSTRING(name, 1, POSITION(' ' IN name) - 1)
    
  • Después comprobamos si ese número está en la lista de cursos de «Bachillerato» o de «Secundaria».
  • Si el número del curso no está en el rango 5–11, mostramos «Primaria».

Sintaxis de la expresión CASE simple

CASE también tiene una sintaxis más sencilla, parecida a la de la expresión CASE de búsqueda, pero menos flexible. En términos generales, tiene este aspecto:

MySQL 8.4
CASE valor
    WHEN valor_comparado THEN resultado
    [WHEN ...]
    [ELSE resultado_por_defecto]
END
  • [ ]parte opcional
  • ...se puede repetir
valor

La expresión que se comprueba, por ejemplo una columna de la tabla.

valor_comparado

Un valor concreto de la rama WHEN, por ejemplo un número o una cadena.

resultado

El valor que devolverá CASE si valor coincide con el valor de la rama.

resultado_por_defecto

El valor para el caso en que no haya coincidencias. Sin ELSE se devuelve NULL.

Opcional

Con esta sintaxis, el valor de CASE se compara uno a uno con los valores indicados en WHEN y, si coincide con alguno, se devuelve el valor que sigue a THEN.

Con esta sintaxis podemos reescribir nuestro ejemplo anterior así:

MySQL 8.4
SELECT name,
CASE SUBSTRING(name, 1, INSTR(name, ' '))
  WHEN 11 THEN 'Bachillerato'
  WHEN 10 THEN 'Bachillerato'
  WHEN 9 THEN 'Secundaria'
  WHEN 8 THEN 'Secundaria'
  WHEN 7 THEN 'Secundaria'
  WHEN 6 THEN 'Secundaria'
  WHEN 5 THEN 'Secundaria'
  ELSE 'Primaria'
END AS stage
FROM Class
MySQL 8.4
SELECT name,
CASE SUBSTRING(name, 1, POSITION(' ' IN name) - 1)
  WHEN '11' THEN 'Bachillerato'
  WHEN '10' THEN 'Bachillerato'
  WHEN '9' THEN 'Secundaria'
  WHEN '8' THEN 'Secundaria'
  WHEN '7' THEN 'Secundaria'
  WHEN '6' THEN 'Secundaria'
  WHEN '5' THEN 'Secundaria'
  ELSE 'Primaria'
END AS stage
FROM Class
namestage
8 ASecundaria
8 BSecundaria
9 CSecundaria
9 BSecundaria
9 ASecundaria
10 BBachillerato
10 ABachillerato
11 BBachillerato
11 ABachillerato
7 ASecundaria
7 BSecundaria
6 ASecundaria
6 BSecundaria
5 ASecundaria
5 BSecundaria
4 APrimaria

Ponte a prueba

¿Qué valor devolverá la expresión CASE en este caso?

MySQL 8.4
CASE 2
  WHEN 0 THEN 'Cero'
  WHEN 1 THEN 'Uno'
  ELSE 'Muchos'
END