CASE es el if/else de SQL
CASE es la forma de meter lógica condicional dentro de una consulta. Recorre las ramas WHEN en orden, se queda con la primera que coincida y devuelve el valor que va después del THEN. Si ninguna encaja, devuelve lo que esté en ELSE, o NULL si no escribiste ninguno.
La palabra clave acá es expresión. La expresión CASE produce un valor, así que cabe en cualquier lugar donde se acepte un valor: una columna del SELECT, una clave del ORDER BY, el lado derecho de una comparación o un argumento de una función.
Esa es la estructura completa: CASE, uno o más WHEN ... THEN ..., un ELSE opcional, y luego END. El END es obligatorio — olvidarlo es el típico error que se cuela.
Un ejemplo realista con CASE WHEN en SQLite
Imagina que tienes una tabla de pedidos y quieres etiquetar cada fila según su tamaño. Vamos a montar una pequeña tabla en línea para poder lanzar la consulta:
Las ramas se evalúan de arriba hacia abajo. Gana la primera coincidencia, así que conviene ordenarlas de la más específica a la más general. El ELSE actúa como cajón de sastre para todo lo que no coincidió antes; sin él, 1200.00 devolvería NULL en lugar de 'grande'.
Searched CASE vs Simple CASE en SQLite
Lo que viste arriba es la forma searched: cada WHEN lleva su propia condición booleana. Cuando lo único que haces es comparar una misma expresión contra varias constantes, existe una versión más corta: la forma simple.
La expresión que va después de CASE se evalúa una sola vez y se compara con = contra cada valor de WHEN. Queda más limpio cuando haces búsquedas por igualdad sobre una única columna.
Cuidado con un detalle: el CASE simple usa =, y en SQL NULL = NULL no es verdadero. Si status puede ser NULL, las ramas 'A'/'B'/'C' no van a coincidir con él, y caerás en el ELSE. Para tratar el NULL de forma explícita, pásate a la forma searched y escribe WHEN status IS NULL THEN ....
CASE dentro de ORDER BY en SQLite
ORDER BY admite cualquier expresión, así que CASE encaja sin problema. Es muy útil cuando quieres un orden personalizado que no sigue el orden alfabético ni el numérico:
'high' < 'low' < 'medium' por orden alfabético, lo cual no sirve de nada para priorizar. Al mapear cada prioridad a un número con CASE, obtienes el orden que realmente quieres. El , id final rompe los empates de forma estable.
CASE dentro de WHERE
Puedes meter un CASE dentro del WHERE, pero casi nunca hace falta: encadenar AND/OR resulta más claro. Donde sí brilla es cuando la propia condición depende de otro valor:
Los artículos en oferta entran si cuestan menos de 20, y los normales si bajan de 30. El umbral mismo depende de una condición. Sin CASE tendrías que escribir (on_sale = 1 AND price < 20) OR (on_sale = 0 AND price < 30) — el mismo resultado, pero con más ruido.
CASE dentro de funciones de agregación
Aquí es donde CASE realmente brilla. Si lo combinas con SUM o COUNT, puedes calcular totales sobre un subconjunto de filas en una sola pasada — es el equivalente en SQL a "cuéntame cuántas cumplen esto":
El CASE devuelve 1 para las filas que cumplen la condición y 0 para el resto, así que SUM se convierte en un conteo condicional. El mismo truco funciona para los ingresos: devuelves total en las filas que coinciden y 0 en las demás. Una sola pasada por la tabla, varios agregados condicionales.
IIF: el atajo de dos ramas
Cuando solo tienes una condición y dos posibles resultados, SQLite te ofrece IIF(cond, when_true, when_false). Es puro azúcar sintáctico para CASE WHEN cond THEN when_true ELSE when_false END:
Usa IIF cuando la lógica es binaria y queda mejor en una sola línea. Pásate a CASE en cuanto tengas tres o más ramas, necesites tratar NULL por separado o quieras aprovechar el orden de evaluación de varias cláusulas WHEN.
Errores comunes que conviene evitar
Hay un par de cosas con las que casi todo el mundo tropieza:
- Olvidar el
END.CASEabre un bloque yENDlo cierra. SQLite te lanzará un error de sintaxis bastante después del punto donde realmente está el problema. - Sin
ELSE, el resultado esNULL. Si ninguna ramaWHENcoincide y no pusisteELSE, obtienesNULL. A veces es justo lo que buscas; la mayoría de las veces, no. - El orden de las ramas importa. En la forma con búsqueda (searched case), gana el primer
WHENque coincida. Si ponesWHEN total < 500antes queWHEN total < 100, la segunda rama nunca se va a ejecutar. - Mezcla de tipos. Cada rama puede devolver un tipo distinto y SQLite no se queja, pero el código que consuma el resultado sí podría hacerlo. Intenta que todas las ramas devuelvan tipos compatibles (todo texto, o todo numérico).
- El
CASEsimple y losNULL. Como ya comentamos: la forma simple usa=, que nunca casa conNULL. Si hay nulos de por medio, usa la forma con búsqueda.
Siguiente paso: funciones de cadenas
Con CASE decides en función de valores; en el próximo capítulo vamos a empezar a transformar valores. Las funciones de cadenas — UPPER, LOWER, SUBSTR, REPLACE y los patrones LIKE — son las que se encargan del trabajo del día a día: limpiar y reformatear columnas de texto. Eso es lo que viene a continuación.
Preguntas frecuentes
¿Qué es una expresión CASE en SQLite?
CASE es la versión SQL del clásico if/else: evalúa condiciones y devuelve un valor. Lo importante es que es una expresión, no una sentencia, así que puedes meterla en cualquier sitio donde quepa un valor: en SELECT, WHERE, ORDER BY, UPDATE e incluso dentro de funciones de agregación. Cada rama tiene la forma WHEN condición THEN valor, con un ELSE final opcional.
¿Cuál es la diferencia entre CASE simple y CASE con búsqueda en SQLite?
Un CASE simple compara una expresión contra varios valores: CASE status WHEN 'A' THEN ... WHEN 'B' THEN ... END. Un CASE con búsqueda evalúa una condición booleana distinta en cada rama: CASE WHEN price > 100 THEN ... WHEN qty = 0 THEN ... END. La forma con búsqueda es más flexible, porque te permite combinar columnas, operadores y comprobaciones de NULL sin restricciones.
¿Cuándo conviene usar IIF en lugar de CASE en SQLite?
IIF(cond, a, b) es básicamente un atajo de CASE WHEN cond THEN a ELSE b END. Tira de IIF cuando solo tengas dos ramas y quede más limpio. Quédate con CASE en cuanto aparezcan tres o más ramas, necesites aprovechar el orden de evaluación o quieras tratar los NULL de forma explícita con WHEN col IS NULL.