Aprende leyendo en orden

Funciones ⑥ — CASE en la práctica — ORDER BY / UPDATE / NULL

El sexto artículo sobre funciones SQL. Asignar un orden arbitrario con ORDER BY CASE, actualizaciones masivas condicionales con UPDATE ~ SET columna = CASE, y el manejo de CASE con NULL — usando datos staff y customer cargados desde CSV.

Datos usados en este artículo — staff y customer

El CASE aprendido hasta ahora es una expresión de propósito general que puedes colocar no solo en la lista de columnas del SELECT sino también dentro de `ORDER BY` y en una cláusula SET de `UPDATE`. Este artículo recorre esas dos aplicaciones y la trampa de manejar NULL con CASE en orden.

El sujeto es la tabla staff (10 empleados) en la primera mitad y la tabla customer (8 clientes / contiene NULL) en la segunda. La primera mitad ordena city en un orden arbitrario; la segunda mitad usa un CASE que muestra el email NULL como "Not registered", y finalmente ejecuta un UPDATE CASE que reescribe los valores de country en categorías de región.

Antes de los ejercicios, confirmemos las definiciones de columnas y una muestra de datos de las dos tablas usadas aquí — staff y customer.

① Usa PRAGMA table_info(staff); y PRAGMA table_info(customer); para revisar las definiciones de columnas de ambas tablas.

② Usa SELECT * FROM staff LIMIT 5; y SELECT * FROM customer LIMIT 5; para previsualizar las primeras 5 filas.

Editor SQL

Ejecutar una consulta para ver el resultado

Usar CASE en ORDER BY — asignar un orden arbitrario

El lado derecho de ORDER BY puede contener no solo un nombre de columna sino también una expresión CASE. Con esto puedes asignar un orden arbitrario que el orden alfabético de cadenas o el tamaño numérico no pueden producir. Úsalo para prioridades de negocio como "Tokyo → Osaka → Kyoto → otros", órdenes de estado como "Open → In progress → Done", o un orden por ranking.

Escríbelo como ORDER BY CASE WHEN cond THEN número ... ELSE número END — CASE devuelve un número para ordenar y ordenas por ese número. ASC / DESC se pueden añadir igual que a una columna. Las filas con el mismo número se ordenan por la siguiente columna de ORDER BY (separada por comas), así que combinar clave de orden + clave secundaria también determina el orden dentro de una categoría.

ORDER BY CASE — asignar un orden arbitrario
citynúmero asignado por CASEordenTokyo11.ºOsaka22.ºKyoto33.ºotros9 (ELSE)último
CASE devuelve un número de ordenación como "1 para Tokyo, 2 para Osaka, …" y haces ORDER BY de ese número. Esto expresa un orden de categorías arbitrario que el orden de cadenas no puede producir.
-- 1) Ordena city en el orden 'Osaka → Kyoto → Tokyo → otros'
SELECT name, city, salary FROM staff
ORDER BY
  CASE city
    WHEN 'Osaka' THEN 1
    WHEN 'Kyoto' THEN 2
    WHEN 'Tokyo' THEN 3
    ELSE 9
  END,
  salary DESC;  -- dentro de la misma city, primero el salario más alto

-- 2) ORDER BY CASE + DESC también puede invertir el orden
--   si CASE asigna 1, 2, 3, entonces DESC los ordena 3, 2, 1

Imagina el requisito "mostrar al personal en orden del tamaño de la oficina (Tokyo → Osaka → Kyoto → otros)". (La explicación aparece cuando lo ejecutas correctamente).

① De la tabla staff, toma las 2 columnas name, city.

② Con ORDER BY CASE, asigna "Tokyo es 1, Osaka es 2, Kyoto es 3, todo lo demás es 9" y ordena por ese número. Hazlo una ordenación multinivel donde las filas dentro de la misma city se ordenen por name ascendente.

Editor SQL

Ejecutar una consulta para ver el resultado

La trampa de CASE + NULL — usa `IS NULL`, no `= NULL`

Igual que en WHERE, `= NULL` / `<> NULL` tampoco se pueden usar dentro de CASE. Una comparación con NULL siempre resulta en NULL (desconocido), y cuando una cláusula CASE WHEN devuelve NULL esa rama no se toma, así que el resultado difiere de lo que pretendías.

Para probar si hay NULL, usa `columna IS NULL` / `columna IS NOT NULL`. Esta es la misma regla que la comprobación de NULL en WHERE aprendida antes, y es común a todo lugar donde se pueda escribir una condición — CASE / IIF / WHERE / ON. La forma simple (CASE columna WHEN ... THEN) no puede probar si hay NULL, así que cuando necesites manejar NULL usa siempre la forma con búsqueda (CASE WHEN columna IS NULL THEN ...).

Cómo manejar NULL con CASE
Forma incorrectaForma correctaCASE name WHEN NULL THEN 'Unknown' ELSE nameENDCASE WHEN name IS NULL THEN 'Unknown' ELSE nameENDWHEN NULL nunca coincide→ 'Unknown' nunca apareceIS NULL detectaNULL correctamente
La forma simple no puede escribir NULL directamente en WHEN. Al manejar NULL, cambia a la forma con búsqueda y usa IS NULL / IS NOT NULL.
-- Incorrecto: WHEN NULL no puede seleccionar filas NULL ('Unknown' nunca se muestra)
SELECT name, age,
  CASE age
    WHEN NULL THEN 'Unknown'
    ELSE age
  END AS age_display
FROM customer;

-- Correcto: forma con búsqueda + IS NULL
SELECT name, age,
  CASE
    WHEN age IS NULL THEN 'Unknown'
    ELSE age
  END AS age_display
FROM customer;

-- Nota: COALESCE(age, 'Unknown') da el mismo resultado
--   para un simple reemplazo de NULL de 2 valores, COALESCE es más corto

Imagina el requisito "en una pantalla de lista de clientes, mostrar el NULL de la columna email como 'Not registered' en vez de un espacio en blanco".

① De la tabla customer, toma name y email.

② Usando la forma CASE con búsqueda, añade una 3.ª columna con el alias email_display que sea 'Not registered' para las filas donde email es NULL, y el valor original de email en otro caso.

Editor SQL

Ejecutar una consulta para ver el resultado

Usar CASE en UPDATE — reescribir valores según una condición

Hasta ahora CASE ha generado una columna nueva en el lado de lectura, pero escribir CASE en una cláusula SET de UPDATE te permite reescribir los valores reales de la columna en la tabla según una condición.

Escríbelo como UPDATE tabla SET columna = CASE WHEN cond THEN valor1 WHEN cond THEN valor2 ... ELSE columna END. Escribir ELSE columna para decir "las filas que no coinciden con ningún WHEN conservan su valor original" es la forma segura; olvídalo y ELSE se trata como NULL, sobrescribiendo con NULL las filas que no son objetivo.

Como UPDATE es una operación destructiva que cambia la tabla real, este artículo lo trata en el ejercicio final. Antes de ejecutarlo, la práctica estándar en producción es probar la misma condición con SELECT name, columna, CASE ..., verificar visualmente el resultado y reescribirlo como UPDATE solo si tiene buen aspecto.

-- Primero verifica con SELECT (con la intención de poner a 0 el age NULL)
SELECT name, age,
  CASE
    WHEN age IS NULL THEN 0
    ELSE age
  END AS new_age
FROM customer;

-- Si tiene buen aspecto, reescríbelo como UPDATE
UPDATE customer SET age = CASE
  WHEN age IS NULL THEN 0
  ELSE age
END;

Imagina el requisito "convertir masivamente la columna country de la tabla customer de nombres de país a categorías de región (Asia / Western / Europe / Unknown)". Este es el ejercicio final del artículo, así que realizas una operación destructiva que cambia la tabla real.

UPDATE masivo de la columna country de la tabla customer con CASE. El mapeo es:

- Japan → Asia

- US o UK → Western

- Italy → Europe

- NULL → Unknown

- Cualquier otra cosa → conserva el valor original (de modo que volver a ejecutarlo da el mismo resultado)

② Tras el UPDATE, ejecuta SELECT id, name, country FROM customer ORDER BY id; y confirma que el país de cada cliente ha cambiado a un nombre de región.

Editor SQL

Ejecutar una consulta para ver el resultado
QUIZ

Verificación de conocimientos

Responde cada pregunta una a una.

Pregunta 1¿Cuál de las siguientes describe correctamente ORDER BY CASE WHEN city = 'Tokyo' THEN 1 WHEN city = 'Osaka' THEN 2 ELSE 9 END?

Pregunta 2¿Cuál de las siguientes es la forma correcta de manejar NULL con CASE?

Pregunta 3En UPDATE customer SET country = CASE WHEN country IN ('Japan') THEN 'Asia' WHEN country IS NULL THEN 'Unknown' ELSE country END;, ¿cuál es la mejor razón para escribir `ELSE country`?