- Aprender
- Informática
- Programación
- Fundamentos de SQL
- Columnas calculadas en SQL
Columnas calculadas en SQL: funciones y CASE
PrincipianteUnidad 3 de 6 del curso Curso de Fundamentos de SQL
Lo que aprenderás
- Calcula nuevos valores para cada fila con operaciones aritméticas y funciones, asigna nombres claros a los resultados y evita que los tipos de datos cambien la respuesta.
- Calcula nuevas columnas y asígnales nombres mediante aliasEscribe expresiones en la lista SELECT, etiqueta los resultados con AS y comprende en qué partes de una consulta se pueden utilizar esas etiquetas.
- Realiza cálculos con operadores aritméticos y funciones numéricasUtiliza +, -, *, / y % en el orden correcto, evita sorpresas con la división entera y redondea los resultados con ROUND y funciones relacionadas.
- Convierte valores entre tipos de datosReconoce el tipo de cada valor, conviértelo explícitamente con CAST e identifica las conversiones automáticas que cambian la ordenación, las comparaciones y los resultados.
- Calcula nuevas columnas y asígnales nombres mediante alias
- Predice cómo afecta NULL a los cálculos, las comparaciones y los filtros, y sustituye o genera valores ausentes de forma deliberada.
- Predice cómo se comporta NULL en cálculos y condicionesExplica qué significa NULL, cómo se propaga por las expresiones y por qué una condición que encuentra NULL no es ni verdadera ni falsa.
- Sustituye y genera valores ausentes con COALESCE y NULLIFRellena los valores ausentes con COALESCE, convierte ceros y valores marcadores en NULL con NULLIF y elige valores de sustitución que conserven el significado de los datos.
- Predice cómo se comporta NULL en cálculos y condiciones
- Concatena, limpia, mide y recorta valores de texto para que los nombres, las direcciones de correo electrónico y los códigos sean uniformes y utilizables.
- Concatena y limpia valores de textoConcatena texto, cambia entre mayúsculas y minúsculas, elimina espacios de los extremos y sustituye caracteres; anida estas funciones para limpiar entradas desordenadas.
- Mide y extrae partes del textoCuenta caracteres, encuentra la posición en la que aparece un carácter y extrae fragmentos de texto utilizando posiciones que empiezan en 1.
- Concatena y limpia valores de texto
- Escribe y lee correctamente los valores de fecha, extrae sus componentes y dales formato, y realiza cálculos con días, meses y períodos de tiempo.
- Escribe, almacena y lee valores de fecha y horaConoce los tipos de fecha y hora, escribe fechas en el formato ISO inequívoco, convierte texto en fechas y obtén la fecha y la hora actuales.
- Extrae partes de las fechas y dales formatoExtrae el año, el mes o el día de la semana, agrupa fechas por períodos y convierte fechas en texto legible.
- Realiza cálculos con fechas y filtra por intervalos de fechasAñade días y meses, mide el tiempo entre dos fechas y escribe filtros de fecha que incluyan todas las filas de un período.
- Escribe, almacena y lee valores de fecha y hora
- Convierte condiciones en etiquetas, categorías y órdenes personalizados con CASE, y combínalo con las demás funciones en consultas completas para informes.
- Clasifica filas en categorías con CASE de búsquedaEscribe CASE WHEN … THEN … ELSE … END, ordena las condiciones para que cada fila quede en el grupo correcto y gestiona los valores límite y los NULL.
- Utiliza CASE simple y aplica CASE en distintas partes de una consultaConvierte códigos en etiquetas con CASE simple, crea indicadores y órdenes personalizados, y reconoce las formas abreviadas que ofrecen otras bases de datos.
- Combina funciones en una consulta completa para informesConstruye paso a paso un informe con varias columnas calculadas, anida correctamente las funciones y comprueba cada columna con filas calculadas a mano.
- Clasifica filas en categorías con CASE de búsqueda
Guía de estudio de Columnas calculadas en SQL
1Crea columnas calculadas con expresiones y alias
Las columnas calculadas transforman los valores que ya hay en una fila en respuestas útiles: un importe de línea, un descuento o una variación porcentual. Los alias claros hacen legibles esos resultados, mientras que los paréntesis y los tipos de datos determinan lo que SQL calcula realmente. Construirás expresiones en pequeños pasos, verás por qué la división entera puede eliminar una parte fraccionaria y elegirás conversiones explícitas cuando la forma de almacenamiento no sea adecuada para la operación.
1.1 Calcula nuevas columnas y asígnales nombres mediante alias
Una columna del resultado puede mostrar un valor que no está almacenado en ningún lugar de la tabla. SQL lo calcula a partir de la fila actual. Una expresión combina columnas, valores fijos, operadores y llamadas a funciones.
Calcula un valor para cada fila
SELECT order_id,
quantity * unit_price AS line_total
FROM orders;
Para una cantidad de 3 y un precio unitario de 12,50, la nueva columna muestra 37.5. Cada fila aporta su propia cantidad y precio. La consulta deja intactas las columnas almacenadas. Una función de una sola fila, como ROUND(unit_price, 0), también devuelve un valor por cada fila de entrada. Añadirla a la lista SELECT no combina filas. En cambio, una función de agregación como SUM o AVG calcula un valor para un grupo.
El nombre que sigue a AS es un alias de columna: un encabezado para el resultado. Sin él, SQLite utiliza como encabezado el texto de la expresión; PostgreSQL utiliza ?column? para esta expresión aritmética. AS es opcional, pero facilita distinguir un nombre de una coma ausente.
Elige nombres y comillas
Utiliza un nombre sencillo como line_total: letras, dígitos y guiones bajos, empezando por una letra. Un nombre que contenga un espacio o una palabra reservada necesita comillas dobles: AS "Line Total" o AS "order". Las comillas simples delimitan valores de texto, como 'Boston'. MySQL también acepta comillas invertidas para los nombres y SQL Server acepta corchetes.
PostgreSQL convierte los nombres sin comillas a minúsculas: AS LineTotal produce linetotal. Las comillas dobles conservan la escritura en AS "LineTotal". SQLite conserva el alias tal como se escribió. Los nombres en minúsculas con guiones bajos funcionan bien en ambos.
Utiliza un alias en la etapa adecuada
El orden lógico es FROM, WHERE, SELECT y, después, ORDER BY. Se elige la tabla y se filtran las filas antes de que las expresiones de salida reciban sus alias. La ordenación se realiza después.
SELECT order_id,
quantity * unit_price AS line_total
FROM orders
WHERE quantity * unit_price > 100
ORDER BY line_total DESC;
ORDER BY puede utilizar line_total. SQL estándar, PostgreSQL y MySQL no pueden utilizar ese nuevo alias en WHERE; repite allí la expresión. SQLite acepta un alias en WHERE como una extensión, pero esa forma fallará al trasladarla a PostgreSQL.
Un alias nuevo tampoco está disponible para otra expresión de la misma lista SELECT. Después de unit_price * 1.08 AS with_tax, escribir with_tax - unit_price AS tax falla si la tabla no tiene una columna with_tax. Escribe en su lugar unit_price * 1.08 - unit_price AS tax.
Diagnostica un resultado inesperado
SELECT first_name last_name FROM customers; es SQL válido. Muestra una columna de nombres con el alias last_name. Para recuperar ambas columnas, escribe SELECT first_name, last_name FROM customers;. Por tanto, una coma ausente puede producir un resultado engañoso sin generar un error.
Para comprobar rápidamente una expresión, no hace falta una tabla: SELECT 19.99 * 3 AS total; devuelve 59.97 en SQLite y PostgreSQL. Oracle anterior a la versión 23 exige FROM DUAL para esta consulta; la versión 23 y las posteriores también permiten SELECT sin FROM.
Puntos clave
- Una columna calculada obtiene un valor para cada fila sin cambiar los datos almacenados.
- Una función de una sola fila conserva las filas; una función de agregación combina valores de un grupo.
- Utiliza comillas dobles para los nombres que las necesiten y comillas simples para los valores de texto.
- ORDER BY puede utilizar un alias de salida; repite la expresión en WHERE para que funcione en distintas bases de datos.
- Un alias nuevo no está disponible en otras expresiones de la misma lista SELECT.
- Una coma ausente puede convertir el siguiente nombre de columna en un alias.
1.2 Realiza cálculos con operadores aritméticos y funciones numéricas
Las expresiones aritméticas transforman cantidades originales en importes, tasas y diferencias. Los operadores son +, -, *, / y %; el módulo da el resto de la división.
Controla el orden del cálculo
La multiplicación, la división y el módulo se realizan antes que la suma y la resta. Los operadores de igual prioridad se evalúan de izquierda a derecha. Así, 10 + 3 * 2 da 16, mientras que (10 + 3) * 2 da 26.
Para una cantidad de 3, un precio unitario de 12,50 y un porcentaje de descuento de 10:
quantity * unit_price * (1 - discount_pct / 100.0)
Primero, 10 / 100.0 da 0.1. Los paréntesis dan la fracción que se paga, 0.9. El importe bruto es 37.5, por lo que el importe neto es 33.75. Sin paréntesis, quantity * unit_price * 1 - discount_pct / 100.0 resta 0.1 de 37.5 y da 37.4.
Conserva la parte fraccionaria al dividir
En SQLite, PostgreSQL y SQL Server, dividir un entero por otro elimina la parte fraccionaria hacia cero: 7 / 2 da 3 y -7 / 2 da -3. MySQL y Oracle dan un resultado decimal para /. En SQLite y PostgreSQL, convierte un operando en decimal antes de dividir: 7 / 2.0, 7 * 1.0 / 2 o CAST(7 AS REAL) / 2 da 3.5. CAST(7 / 2 AS REAL) llega demasiado tarde y da 3.0.
Para una subida de 80 a 92, (92 - 80) * 100.0 / 80 da 15.0 por ciento. Dividir primero la diferencia entera por 80 elimina la parte fraccionaria. El módulo conserva lo que sobra: 135 / 60 da 2 horas y 135 % 60 da 15 minutos. En SQLite y PostgreSQL, -7 % 3 da -1; el resto sigue el signo del operando izquierdo. Oracle escribe MOD(17, 5) en lugar de %.
Un divisor cero genera un error en PostgreSQL y SQL Server; SQLite y MySQL devuelven NULL. amount / NULLIF(divisor, 0) hace que el caso de cero devuelva NULL en todos estos sistemas.
Redondea o elige un número entero
ROUND(x, n) redondea a n decimales. Una lámpara con un precio de 24,00 y un coste de 15,50 tiene un beneficio de 8.5. ROUND((price - cost) / price * 100, 1) da un margen de 35.4 por ciento. PostgreSQL admite un número de decimales negativo: ROUND(1234.5678, -2) da 1200; SQLite lo trata como cero y da 1235.0.
| Función | Significado | Ejemplo |
|---|---|---|
ABS | Distancia a cero | ABS(-4.2) da 4.2 |
CEIL | Menor entero mayor o igual al valor | CEIL(4.1) da 5 |
FLOOR | Mayor entero menor o igual al valor | FLOOR(-4.1) da -5 |
TRUNC | Elimina la parte fraccionaria hacia cero | TRUNC(42.8) da 42 |
PostgreSQL proporciona estas funciones. SQLite proporciona ABS; CEIL, FLOOR y TRUNC requieren una versión compilada con funciones matemáticas, disponibles desde la 3.35.
Ajusta la precisión a los datos
ROUND de SQLite y ROUND con numeric de PostgreSQL redondean los valores exactamente a mitad alejándose de cero: ROUND(-2.5) da -3. El redondeo de coma flotante de PostgreSQL suele resolver los empates con el entero par más cercano; su ROUND de dos argumentos requiere numeric, por lo que debes utilizar ROUND(CAST(x AS numeric), 2) para una columna de doble precisión.
Los números de coma flotante aproximan muchas fracciones decimales. SQLite puede hacer que 0.1 + 0.2 = 0.3 sea falso y que ROUND(2.675, 2) devuelva 2.67. Los literales decimales de PostgreSQL utilizan numeric exacto. Para importes monetarios exactos, utiliza NUMERIC/DECIMAL en PostgreSQL o céntimos expresados como enteros en SQLite. Declarar DECIMAL en SQLite no crea un almacenamiento decimal exacto. Conserva la precisión durante los cálculos y redondea para mostrar los resultados.
Puntos clave
- Los paréntesis controlan qué cantidades se combinan antes de multiplicar o dividir.
- Convierte un operando antes de la división entera; convertir el resultado no recupera los dígitos perdidos.
- El módulo devuelve un resto, como los minutos que sobran después de contar las horas completas.
- ROUND, FLOOR, CEIL y TRUNC toman decisiones distintas sobre un valor con parte fraccionaria.
- El redondeo de coma flotante y las funciones numéricas disponibles dependen del tipo y de la base de datos.
- Utiliza almacenamiento numérico exacto en PostgreSQL o céntimos expresados como enteros en SQLite para obtener importes exactos.
- NULLIF puede hacer que un divisor cero produzca NULL en lugar de un error.
1.3 Convierte valores entre tipos de datos
El tipo de datos de un valor afecta a las operaciones aritméticas, las comparaciones y la ordenación. El número 42 es distinto del texto '42', aunque una cuadrícula de resultados los muestre de la misma manera.
Convierte un valor explícitamente
Los tipos habituales incluyen INTEGER para números enteros, NUMERIC o DECIMAL para decimales exactos en PostgreSQL, REAL o double precision para números aproximados, TEXT o VARCHAR para texto, y DATE, TIME, TIMESTAMP y BOOLEAN donde estén disponibles.
SELECT CAST('42' AS INTEGER) AS number_value,
CAST(42 AS TEXT) AS text_value;
CAST(expression AS type) forma parte de SQL estándar. El primer resultado es un número; el segundo es texto. PostgreSQL también acepta '42'::integer. Convertir NULL sigue dando NULL.
Para la división decimal en SQLite, escribe CAST(quantity AS REAL) / 4; en PostgreSQL, escribe CAST(quantity AS NUMERIC) / 4. Una cantidad de 7 da 1.75. CAST(7 AS NUMERIC) / 2 de SQLite sigue dando 3: NUMERIC deja ese valor entero almacenado como un entero. REAL es el tipo adecuado para esta conversión en SQLite.
Comprende qué hace una conversión a entero
| Entrada y conversión | SQLite | PostgreSQL |
|---|---|---|
CAST(3.9 AS INTEGER) | 3 | 4 |
CAST(-3.9 AS INTEGER) | -3 | -4 |
CAST('abc' AS INTEGER) | 0 | Error |
SQLite elimina la parte fraccionaria hacia cero. PostgreSQL redondea un valor numérico al entero más cercano. Utiliza primero ROUND, TRUNC, FLOOR o CEIL cuando importe la regla que se deba aplicar. PostgreSQL rechaza el texto que no sea un número válido. SQLite lee una parte numérica inicial: '12abc' se convierte en 12 y '12.5' se convierte en 12 al convertirlos a INTEGER. Por tanto, obtener cero tras una conversión en SQLite no demuestra que el texto original fuera un cero válido. TRY_CAST de SQL Server devuelve NULL si la conversión falla.
Distingue las cantidades de los identificadores
El texto se ordena carácter por carácter. Las cadenas '9', '10' y '100' se ordenan como '10', '100', '9'. Para ordenar cantidades realmente numéricas almacenadas como texto, utiliza ORDER BY CAST(code AS INTEGER) después de asegurarte de que sean números válidos.
Un código postal estadounidense ZIP como '02134' es un identificador. Convertirlo da 2134 y pierde el primer cero. Los números de teléfono también deben ser texto: sus dígitos identifican algo, en lugar de describir una cantidad que se pueda sumar o promediar.
Reconoce las conversiones automáticas
Tanto SQLite como PostgreSQL convierten el número en texto en 'Order #' || 42, produciendo 'Order #42'. Ambos también evalúan como número el literal entre comillas de '5' + 3. En PostgreSQL, ese literal tiene inicialmente un tipo sin determinar; una columna TEXT no tiene la misma flexibilidad. Sumar 3 a una columna TEXT falla, por lo que debes convertir la columna explícitamente.
SQLite asigna a las columnas una preferencia de tipo, llamada afinidad de tipo, y puede conservar valores de distintos tipos en una misma columna ordinaria. typeof(42), typeof(4.2), typeof('42') y typeof(NULL) devuelven 'integer', 'real', 'text' y 'null'. SQLite no tiene un tipo DATE específico: CAST('2026-03-14' AS DATE) da 2026. Utiliza date('2026-03-14') para sus funciones de fecha.
Oracle proporciona TO_NUMBER, TO_CHAR y TO_DATE. TO_CHAR y TO_DATE de PostgreSQL reciben patrones de formato como 'MM/DD/YYYY'. CONVERT de SQL Server utiliza un código numérico de estilo: CONVERT(date, '03/14/2026', 101) interpreta el formato de fecha estadounidense.
Puntos clave
- CAST cambia explícitamente un valor al tipo solicitado; NULL sigue siendo NULL.
- SQLite trunca las conversiones de números a enteros, mientras que PostgreSQL las redondea.
- SQLite puede convertir texto numérico no válido en un número parcial o en cero.
- Conserva los códigos postales estadounidenses ZIP y los números de teléfono como texto para preservar su identidad.
- La ordenación de texto y la ordenación numérica pueden producir órdenes distintos.
2Gestiona los valores ausentes con la lógica de NULL y COALESCE
Un valor ausente puede cambiar un cálculo y también las filas que conserva un filtro. Comprender NULL requiere seguir tanto el dato como la condición que lo utiliza. Distinguirás la ausencia de datos del cero y de la cadena vacía, seguirás TRUE, FALSE y UNKNOWN a través de una consulta y elegirás valores de sustitución que conserven el significado de un informe. COALESCE y NULLIF te permitirán rellenar valores ausentes o generarlos deliberadamente.
2.1 Predice cómo se comporta NULL en cálculos y condiciones
NULL indica un valor ausente o desconocido. Una celda vacía del resultado podría representar NULL, pero NULL no es un valor ordinario que puedas comparar con =.
Sigue una entrada ausente a través de una expresión
Cero es un número conocido. La cadena vacía, '', es una cadena conocida sin caracteres. El texto 'N/A' es una etiqueta registrada. NULL indica que no hay ningún valor disponible. Oracle trata la cadena vacía como NULL; SQLite y PostgreSQL los distinguen.
La mayoría de las operaciones aritméticas y funciones propagan una entrada ausente como NULL. Con un salario de 50 000 y una bonificación NULL, salary + bonus da NULL. El total es desconocido porque la bonificación es desconocida. UPPER(NULL), ROUND(NULL, 2) y 'Ana ' || NULL también devuelven NULL en SQLite y PostgreSQL.
Comprueba NULL directamente
bonus = NULL, bonus <> NULL e incluso NULL = NULL producen UNKNOWN. No se sabe si dos valores ausentes son iguales. Utiliza bonus IS NULL o bonus IS NOT NULL. Estas comprobaciones siempre devuelven TRUE o FALSE.
SQL tiene tres resultados posibles: TRUE, FALSE y UNKNOWN. SQLite muestra TRUE como 1, FALSE como 0 y UNKNOWN como NULL.
| Condición | Resultado | Motivo |
|---|---|---|
FALSE AND UNKNOWN | FALSE | Un requisito falso descarta AND |
TRUE AND UNKNOWN | UNKNOWN | El segundo requisito sigue sin resolverse |
TRUE OR UNKNOWN | TRUE | Una alternativa verdadera determina OR |
FALSE OR UNKNOWN | UNKNOWN | La alternativa restante sigue sin resolverse |
NOT UNKNOWN | UNKNOWN | Negar un valor desconocido no lo resuelve |
Comprende qué filas conserva WHERE
WHERE solo conserva TRUE. Tanto FALSE como UNKNOWN excluyen la fila. Para bonificaciones de 1000, 0, NULL, 2500 y NULL, WHERE bonus < 1000 solo conserva el cero. WHERE bonus >= 1000 conserva 1000 y 2500. Estos filtros abarcan tres filas, no cinco. WHERE NOT (bonus < 1000) también conserva únicamente las dos bonificaciones conocidas de al menos 1000.
El mismo problema afecta a <>. Con las ciudades Boston, Denver, NULL, Boston y Austin, WHERE city <> 'Boston' conserva Denver y Austin. Incluye explícitamente la ciudad desconocida:
WHERE city <> 'Boston' OR city IS NULL
Esto conserva tres filas. NOT no recupera automáticamente los valores ausentes.
Presta atención a las listas y las comparaciones
3 IN (1, 2, NULL) es UNKNOWN: el elemento ausente podría ser 3. Para x NOT IN (1, 2, NULL), un valor coincidente no cumple NOT IN y cualquier valor sin coincidencia da UNKNOWN. En una cláusula WHERE, esta lista fija no conserva ninguna fila. Elimina los NULL no deseados de una lista de exclusión antes de utilizarla.
Para una igualdad que trate dos NULL como iguales, utiliza a IS NOT DISTINCT FROM b. Su opuesto, a IS DISTINCT FROM b, es TRUE cuando un valor es NULL y el otro no; dos NULL no son distintos. PostgreSQL y SQLite desde la versión 3.39 admiten estas formas. SQLite también tiene IS e IS NOT; MySQL escribe la igualdad segura frente a NULL como <=>.
La ordenación predeterminada de NULL varía: SQLite coloca NULL al principio en orden ascendente; PostgreSQL lo coloca al final. Indica su posición cuando importe: ORDER BY bonus DESC NULLS LAST coloca las bonificaciones conocidas en orden descendente y las ausentes al final.
Puntos clave
- NULL significa ausente o desconocido, no cero ni cadena vacía.
- Las comparaciones con NULL producen UNKNOWN; comprueba la ausencia de datos con IS NULL.
- WHERE solo conserva TRUE, por lo que NOT y <> no recuperan las filas con resultados desconocidos.
- AND y OR solo pueden resolver un resultado desconocido cuando la otra condición determina el resultado.
- Un NULL en una lista NOT IN impide que esa condición sea TRUE.
- IS NOT DISTINCT FROM trata dos NULL como iguales.
- NULLS FIRST o NULLS LAST hace explícita la posición de NULL en la ordenación.
2.2 Sustituye y genera valores ausentes con COALESCE y NULLIF
Los valores ausentes a veces necesitan un valor de sustitución y otras veces deben seguir ausentes. La elección forma parte del significado del informe. COALESCE rellena una ausencia; NULLIF convierte un valor marcador coincidente en una ausencia.
Elige el primer valor disponible
COALESCE(a, b, ...) comprueba de izquierda a derecha y devuelve el primer argumento que no sea NULL. Devuelve NULL si todos los argumentos son NULL.
SELECT COALESCE(mobile_phone, home_phone, 'no phone') AS contact
FROM customers;
Sin número de móvil y con el teléfono fijo '555-0100', el contacto es '555-0100'. Si no se ha registrado ninguno de los dos números, es 'no phone'. Un cero conocido o una cadena vacía cuentan como disponibles: COALESCE omite NULL, no los valores que parecen vacíos o falsos.
Para la remuneración, salary + COALESCE(bonus, 0) da 50 000 cuando el salario es 50 000 y la bonificación es NULL. Esto es adecuado cuando una bonificación ausente significa que no se pagó ninguna. La ausencia de una valoración de producto no significa una valoración de cero; sustituirla inventaría una mala valoración. Deja ese número ausente o crea una etiqueta de texto para mostrarlo.
Mantén compatibles los tipos de los valores de sustitución
PostgreSQL no puede combinar un rating entero con el texto 'not rated' en un resultado numérico. Convierte primero las valoraciones conocidas en texto:
COALESCE(CAST(rating AS TEXT), 'not rated')
Una valoración de 4 se muestra como el texto '4'; un NULL se muestra como 'not rated'. SQLite acepta argumentos numéricos y de texto mezclados, pero entonces la salida puede contener distintos tipos. Deja claro el tipo de resultado deseado al trasladar una consulta entre bases de datos.
COALESCE forma parte de SQL estándar y acepta dos o más argumentos. Las alternativas habituales con dos argumentos son IFNULL en SQLite y MySQL, ISNULL en SQL Server y NVL en Oracle.
Convierte un valor marcador en NULL
NULLIF(a, b) devuelve NULL si los argumentos son iguales; en caso contrario, devuelve el primer argumento. NULLIF(0, 0) es NULL, mientras que NULLIF(5, 0) es 5.
Una expresión útil para una tasa es:
orders * 100.0 / NULLIF(visits, 0) AS conversion_pct
Con 12 pedidos y 300 visitas, el divisor sigue siendo 300 y la tasa es 4.0. Con cero visitas, el divisor se convierte en NULL y la tasa pasa a ser NULL. PostgreSQL evita un error de división por cero y el resultado indica correctamente una tasa no definida. Sustituir esa tasa por cero afirmaría algo distinto.
Limpia las ausencias antes de proporcionar una etiqueta
COALESCE(NULLIF(phone, ''), 'unknown')
El NULLIF interno convierte una cadena vacía en NULL. El COALESCE externo etiqueta después tanto un NULL original como una cadena vacía con 'unknown'. Un número de teléfono registrado pasa sin cambios.
Para un segundo nombre opcional, incluye su espacio final dentro de la expresión de sustitución:
first_name || ' ' || COALESCE(middle_name || ' ', '') || last_name
Un segundo nombre NULL no aporta nada, y produce 'Ana Lopez'. Un segundo nombre 'Maria' aporta 'Maria ', y produce 'Ana Maria Lopez'.
Estas expresiones solo cambian el resultado de la consulta. Dejan los valores originales almacenados en la tabla. Un filtro como WHERE COALESCE(bonus, 0) = 0 reúne las bonificaciones conocidas de cero y las ausentes, así que utilízalo cuando esos sean los dos grupos que quieras.
Puntos clave
- COALESCE devuelve el primer argumento que no sea NULL, incluidos un cero conocido o una cadena vacía.
- Un valor de sustitución debe expresar el significado de los datos ausentes y tener un tipo compatible.
- NULLIF devuelve NULL si hay igualdad y, en caso contrario, devuelve su primer argumento.
- Utiliza NULLIF alrededor de un divisor para que un denominador cero produzca NULL.
- Limpia un valor marcador con NULLIF antes de aplicar un valor de sustitución para mostrarlo con COALESCE.
3Limpia, combina y descompón texto con funciones de cadenas
El texto de una tabla a menudo necesita una forma utilizable: un nombre completo, una dirección de correo electrónico uniforme o una parte de un código. SQL puede concatenar y limpiar cadenas, contar sus caracteres y extraer la parte anterior o posterior a un separador. Seguirás las posiciones de los caracteres en cada paso y comprobarás cómo afectan al resultado los espacios, las mayúsculas y minúsculas y NULL. SQLite y PostgreSQL comparten muchas funciones, pero difieren en varios nombres y comportamientos.
3.1 Concatena y limpia valores de texto
SQL trata un valor de texto como una cadena de caracteres. Las funciones de texto pueden construir un nombre completo o limpiar una dirección de correo electrónico para compararla. Sus resultados aparecen en la consulta; el texto almacenado permanece intacto.
Escribe y concatena texto
Los literales de texto utilizan comillas simples. Para incluir un apóstrofo, duplícalo: 'O''Brien' representa «O'Brien». Un par de comillas simples, '', es una cadena vacía.
SELECT first_name || ' ' || last_name AS full_name
FROM customers;
El operador de concatenación || une los fragmentos exactamente como están escritos. Con 'Ana' y 'Lopez', el resultado es 'Ana Lopez'. El literal del medio aporta el espacio; la concatenación no lo inserta automáticamente.
SQLite, PostgreSQL y Oracle utilizan ||. En el modo predeterminado de MySQL, || significa OR, así que utiliza CONCAT allí. SQL Server utiliza + y también admite || desde 2025. Para concatenar un identificador numérico de pedido, SQLite y PostgreSQL lo convierten en texto en 'Order #' || order_id. Con + de SQL Server, convierte primero el número: 'Order #' + CAST(order_id AS VARCHAR(10)).
Elige cómo concatenar una parte ausente
En SQLite y PostgreSQL, un operando NULL hace que el resultado de || sea NULL. Oracle trata esa parte ausente como una cadena vacía. CONCAT también varía según la base de datos:
| Base de datos | CONCAT('Ana', NULL, 'Lopez') |
|---|---|
| PostgreSQL, SQL Server, SQLite desde la versión 3.44 | 'AnaLopez' |
| MySQL | NULL |
CONCAT de Oracle recibe exactamente dos argumentos. CONCAT_WS(' ', first_name, middle_name, last_name) coloca espacios entre las partes que no son NULL, por lo que un segundo nombre ausente da 'Ana Lopez'. SQLite añadió CONCAT y CONCAT_WS en la versión 3.44. Omitir NULL sigue sin eliminar una cadena vacía.
Cambia entre mayúsculas y minúsculas y recorta los extremos
UPPER('boston') da 'BOSTON'; LOWER produce minúsculas. INITCAP('ana LOPEZ') de PostgreSQL da 'Ana Lopez'. SQLite no tiene INITCAP, y su conversión incorporada entre mayúsculas y minúsculas solo cambia A–Z: UPPER('é') sigue siendo 'é' sin la extensión ICU. La conversión de PostgreSQL sigue su configuración regional.
TRIM elimina espacios de ambos extremos; LTRIM los elimina solo al principio y RTRIM solo al final. TRIM(' New York ') da 'New York', conservando los dos espacios interiores. Para eliminar x de ambos extremos, SQLite escribe TRIM('xxBostonxx', 'x'); PostgreSQL escribe TRIM(BOTH 'x' FROM 'xxBostonxx').
Sustituye caracteres y anida los pasos de limpieza
REPLACE('555-0100', '-', '') da '5550100'. Sustituye cada aparición exacta. Las mayúsculas y minúsculas importan: sustituir 'st' en 'Main St' no cambia nada porque 'St' tiene una S mayúscula.
SELECT LOWER(TRIM(email)) AS email_clean
FROM customers;
Para ' Ana@Example.COM ', TRIM produce primero 'Ana@Example.COM' y después LOWER produce 'ana@example.com'. Anidar significa que la función más interna proporciona la entrada de la siguiente.
La igualdad ordinaria de texto distingue mayúsculas y minúsculas de forma predeterminada en SQLite y PostgreSQL. WHERE LOWER(TRIM(email)) = 'ana@example.com' puede encontrar coincidencias con entradas que tengan distintas mayúsculas y espacios en los extremos. La intercalación predeterminada de MySQL ignora las mayúsculas y minúsculas, y LIKE de SQLite ignora esa distinción en A–Z aunque su comparación predeterminada con = no lo haga.
Puntos clave
- Utiliza comillas simples para el texto y duplica un apóstrofo dentro de un literal.
- La concatenación une fragmentos exactos; incluye los separadores explícitamente.
- El comportamiento de NULL varía entre ||, CONCAT y los dialectos de las bases de datos.
- TRIM elimina espacios de los extremos, mientras que REPLACE cambia los caracteres coincidentes en todo el texto.
- Las funciones anidadas se ejecutan de dentro hacia fuera.
- La conversión entre mayúsculas y minúsculas y la búsqueda que las distingue dependen de la base de datos y de la configuración regional.
3.2 Mide y extrae partes del texto
Las funciones de texto localizan y extraen fragmentos según la posición de sus caracteres. SQL empieza a contar las posiciones en 1, por lo que el primer carácter ocupa la posición 1. Una posición encontrada y un número de caracteres son entradas distintas.
Mide y recorta una cadena
LENGTH('Boston') da 6. Los espacios cuentan: LENGTH(' Bo ') da 4. Una cadena vacía tiene longitud 0; LENGTH(NULL) da NULL. LENGTH de MySQL cuenta bytes, así que utiliza CHAR_LENGTH para contar caracteres en ese sistema. SQL Server utiliza LEN, que ignora los espacios finales.
SELECT SUBSTR('Boston', 1, 3) AS beginning,
SUBSTR('Boston', 4) AS ending;
Los resultados son 'Bos' y 'ton'. La primera llamada toma tres caracteres a partir de la posición 1. La segunda omite el número de caracteres y toma todo desde la posición 4 en adelante. PostgreSQL también escribe SUBSTRING('Boston' FROM 4 FOR 3). SQLite acepta el nombre SUBSTRING desde la versión 3.34. SQL Server utiliza SUBSTRING(text, start, count); el número de caracteres es obligatorio hasta 2022 y opcional desde 2025.
SQLite puede contar desde la derecha: SUBSTR('Boston', -3) da 'ton'. Las posiciones iniciales negativas de PostgreSQL no cuentan hacia atrás desde el final. Utiliza allí RIGHT('Boston', 3); LEFT toma caracteres del principio. SQLite no tiene LEFT ni RIGHT.
Encuentra el punto de separación
INSTR(text, search) de SQLite devuelve la posición de la primera coincidencia. PostgreSQL utiliza STRPOS o POSITION(search IN text). Estas funciones devuelven 0 cuando no encuentran ninguna coincidencia. La búsqueda distingue mayúsculas y minúsculas: INSTR('Ana', 'a') da 3.
En 'ana@example.com', el @ está en la posición 4. El nombre de usuario termina justo antes; el dominio empieza justo después:
SUBSTR(email, 1, INSTR(email, '@') - 1) AS user_name,
SUBSTR(email, INSTR(email, '@') + 1) AS domain
La primera expresión se convierte en SUBSTR(email, 1, 3) y produce 'ana'. La segunda empieza en 5 y produce 'example.com'. Omitir - 1 incluye @ en el nombre de usuario. Omitir + 1 lo incluye al principio del dominio. En PostgreSQL, sustituye INSTR por STRPOS o utiliza SPLIT_PART(email, '@', 2) para el dominio.
Gestiona la ausencia de un separador
Para 'anaexample.com', INSTR devuelve 0. La fórmula del dominio empieza en 1 y devuelve toda la cadena de forma engañosa. La fórmula del nombre de usuario en SQLite da una cadena vacía; PostgreSQL rechaza su longitud de subcadena negativa. Protege la extracción:
CASE
WHEN INSTR(email, '@') > 0
THEN SUBSTR(email, INSTR(email, '@') + 1)
END
Esto devuelve NULL cuando falta el separador. La comprobación busca un separador; no verifica todas las reglas de una dirección de correo electrónico válida.
Crea etiquetas breves y códigos de anchura fija
SUBSTR(first_name, 1, 1) || '. ' || last_name da 'A. Lopez' para Ana Lopez. WHERE LENGTH(zip_code) <> 5 encuentra cadenas de códigos postales estadounidenses ZIP registradas con una longitud incorrecta; las longitudes NULL producen UNKNOWN y se excluyen.
LPAD('42', 5, '0') de PostgreSQL da '00042'; RPAD rellena por la derecha. SQLite puede construir ese código con SUBSTR('00000' || 42, -5). Conservar solo cinco caracteres también recorta un valor más largo, por lo que esta expresión de anchura fija necesita un código que quepa.
Puntos clave
- Las posiciones de las cadenas SQL empiezan en 1; LENGTH incluye los espacios.
- SUBSTR recibe una posición inicial y un número opcional de caracteres.
- INSTR, STRPOS y POSITION devuelven 0 cuando no hay coincidencia.
- Utiliza la posición menos 1 antes de un separador y la posición más 1 después de él.
- Comprueba si falta el separador antes de extraer un fragmento.
- La extracción desde el final y el relleno tienen nombres distintos en SQLite y PostgreSQL.
4Trabaja con fechas y horas
El trabajo con fechas empieza por distinguir claramente entre un día del calendario, una hora y una marca de fecha y hora. A partir de ahí, SQL puede crear etiquetas de año y mes, calcular plazos, medir el tiempo transcurrido y filtrar un período completo. Mantendrás separados los valores de fecha del texto para mostrarlos, tendrás en cuenta los finales de mes y los cumpleaños, y compararás las expresiones de SQLite y PostgreSQL que realizan la misma tarea. Los casos límite hacen fiables estos cálculos.
4.1 Escribe, almacena y lee valores de fecha y hora
Es más fácil calcular con una fecha cuando su almacenamiento y su escritura son claros. El texto '03/04/2026' podría significar 4 de marzo o 3 de abril. Una fecha ISO, '2026-03-14', coloca el año, el mes y el día en un orden inequívoco.
Relaciona el valor con su tipo
PostgreSQL tiene DATE para un día del calendario, TIME para una hora del día y TIMESTAMP para una fecha y hora. Su TIMESTAMP WITH TIME ZONE, también llamado timestamptz, almacena un instante en UTC y lo muestra en la zona horaria de la sesión. Un TIMESTAMP simple no incorpora ese significado de zona horaria.
SQLite almacena las fechas y horas como texto ISO o como números, no en tipos específicos de fecha y hora. Las formas numéricas incluyen números de día juliano y tiempo Unix. Las funciones de fecha interpretan estos valores y devuelven una fecha, una hora o una medida numérica.
Utiliza texto ISO de anchura fija como '2026-03-14', incluidos los ceros iniciales. Añade una hora con el formato de 24 horas: '2026-03-14 09:30:00'. El literal con tipo de PostgreSQL DATE '2026-03-14' crea explícitamente una fecha.
Conserva el orden cronológico
El texto ISO de anchura fija se compara en orden cronológico porque empieza por el componente mayor. '2026-03-14' va antes de '2026-11-02'. El texto de presentación estadounidense no tiene esta propiedad: como cadenas, '11/02/2025' se ordena después de '03/14/2026' aunque su fecha sea anterior.
El analizador de SQLite necesita un formato compatible. date('2026-3-14') devuelve NULL porque el mes no tiene dos dígitos. También puede normalizar una fecha imposible: date('2026-02-30') devuelve '2026-03-02'. Un resultado que no sea NULL no demuestra por sí solo que la entrada fuera un día válido del calendario. PostgreSQL rechaza DATE '2026-02-30'.
Lee texto en otro formato
PostgreSQL y Oracle utilizan TO_DATE('03/14/2026', 'MM/DD/YYYY') para leer un formato estadounidense. PostgreSQL también lee texto ISO con CAST('2026-03-14' AS DATE) o '2026-03-14'::date.
SQLite no tiene un analizador TO_DATE. Para texto de formato fijo MM/DD/YYYY en d, reconstruye el texto ISO:
SUBSTR(d, 7, 4) || '-' ||
SUBSTR(d, 1, 2) || '-' || SUBSTR(d, 4, 2)
Los fragmentos son el año '2026', el mes '03' y el día '14'. El resultado es '2026-03-14', que las funciones de fecha de SQLite pueden leer. Las posiciones dependen de que la entrada utilice realmente ese formato fijo.
Obtén la fecha y la hora actuales
CURRENT_DATE y CURRENT_TIMESTAMP funcionan en SQLite y PostgreSQL. SQLite devuelve texto UTC; date('now', 'localtime') da la fecha local. Cerca de medianoche, la fecha UTC y la fecha local del calendario pueden diferir.
PostgreSQL utiliza la zona horaria de la sesión. CURRENT_TIMESTAMP y NOW() reflejan el inicio de la transacción actual, por lo que esperar dentro de esa transacción no hace avanzar su valor. MySQL ofrece NOW() y CURDATE(); SQL Server tiene GETDATE() y SYSDATETIME(); Oracle tiene SYSDATE, que incluye una hora, y CURRENT_DATE.
Para comprobar un cálculo de vencimiento, utiliza primero una referencia fija como DATE '2026-10-21' en PostgreSQL o '2026-10-21' en SQLite. Así podrás comparar el resultado con un calendario sin que la respuesta cambie al día siguiente.
Puntos clave
- DATE es un día del calendario; TIMESTAMP añade una hora del día.
- Utiliza YYYY-MM-DD de anchura fija para que el texto de fecha sea inequívoco y funcione en distintas bases de datos.
- El texto ISO se ordena cronológicamente cuando su formato y su referencia horaria son uniformes.
- Un resultado de fecha de SQLite puede normalizar una entrada imposible en lugar de rechazarla.
- Las funciones de fecha actual utilizan distintas reglas de zona horaria y transacción.
4.2 Extrae partes de las fechas y dales formato
Extrae un componente de una fecha cuando necesites un año o un día de la semana para calcular. Da formato a una fecha cuando necesites texto para el lector. Estas operaciones pueden producir tipos distintos aunque los caracteres mostrados parezcan iguales.
Extrae un año, un mes o un día de la semana
PostgreSQL utiliza la forma estándar EXTRACT(part FROM value). Para DATE '2026-03-14', extraer YEAR da 2026 y MONTH da 3, ambos como números. MySQL y Oracle también admiten EXTRACT.
SQLite utiliza strftime(format, value), que devuelve texto:
| Patrón de SQLite | Resultado para '2026-03-14' |
|---|---|
'%Y' | '2026' |
'%m' | '03' |
'%d' | '14' |
'%w' | '6' |
%w de SQLite y DOW de PostgreSQL numeran desde el domingo como 0 hasta el sábado como 6. El 14 de marzo de 2026 es sábado. En cambio, ISODOW de PostgreSQL numera desde el lunes como 1 hasta el domingo como 7. Un filtro de fin de semana en SQLite es WHERE strftime('%w', order_date) IN ('0', '6').
Compara los tipos adecuados
strftime('%m', order_date) = 3 es falso para una fecha de marzo en SQLite: la función devuelve el texto '03', no el número 3. Compáralo con = '03' o conviértelo primero:
CAST(strftime('%m', order_date) AS INTEGER) = 3
Esto también resulta útil en la expresión del trimestre (CAST(strftime('%m', d) AS INTEGER) + 2) / 3. La división entera da el trimestre 1 para marzo y el trimestre 4 para noviembre. PostgreSQL dispone directamente de EXTRACT(QUARTER FROM d).
Identifica un mes como un período completo
strftime('%Y-%m', order_date) crea una etiqueta de SQLite como '2026-03'. date(order_date, 'start of month') crea '2026-03-01'. PostgreSQL puede utilizar TO_CHAR(order_date, 'YYYY-MM') para una etiqueta o DATE_TRUNC('month', order_date) para el primer instante de ese mes.
Conserva el año en una etiqueta de período. Un valor de mes de 3 por sí solo combinaría marzo de distintos años. El valor del primer día del mes puede seguir utilizándose para calcular y ordenar, mientras otra expresión proporciona el texto que se muestra.
Da formato en la etapa de salida
En PostgreSQL, TO_CHAR(DATE '2026-03-14', 'MM/DD/YYYY') da '03/14/2026', y el patrón 'Mon DD, YYYY' da 'Mar 14, 2026'. Oracle también utiliza estos patrones. El formato estadounidense de SQLite es strftime('%m/%d/%Y', '2026-03-14').
Las letras de los patrones son propias de cada base de datos. En PostgreSQL, MM significa mes y MI significa minuto. En SQLite, %m significa mes y %M significa minuto; cambiar esa mayúscula cambia la información solicitada.
SELECT TO_CHAR(order_date, 'MM/DD/YYYY') AS order_day
FROM orders
ORDER BY order_date;
Aquí PostgreSQL muestra texto legible, pero ordena las fechas reales. Ordenar por order_day ordenaría las cadenas mostradas empezando por el mes y podría colocar fuera de orden fechas de distintos años.
Puntos clave
- EXTRACT de PostgreSQL devuelve componentes numéricos; strftime de SQLite devuelve texto.
- Compara un mes de SQLite con cero inicial con texto, o conviértelo en un número.
- La numeración de los días de la semana depende de la convención solicitada.
- Conserva el año en las etiquetas de año y mes y da formato solo para mostrar los resultados.
4.3 Realiza cálculos con fechas y filtra por intervalos de fechas
Los cálculos de calendario deben tener en cuenta la duración de los meses, los componentes horarios y el tipo de respuesta necesario. Un número de días, un mes del calendario y un año cumplido de edad son medidas distintas.
Añade días y meses del calendario
PostgreSQL escribe DATE '2026-03-14' + 30; SQLite escribe date('2026-03-14', '+30 days'). Ambos llegan al 13 de abril: 17 días completan marzo y otros 13 llegan al 13 de abril. En cambio, la expresión directa de SQLite '2026-03-14' + 30 da 2056, porque la operación aritmética interpreta el año inicial como un número.
Los finales de mes necesitan una regla explícita. DATE '2026-01-31' + INTERVAL '1 month' de PostgreSQL da el 28 de febrero a medianoche, utilizando el último día disponible. date('2026-01-31', '+1 month') de SQLite desplaza los días sobrantes a marzo y da '2026-03-03'. Desde SQLite 3.46, añade 'floor' después del desplazamiento para elegir '2026-02-28'. ADD_MONTHS de Oracle también se desplaza al último día del mes más corto.
Mide el tiempo transcurrido
La resta de DATE en PostgreSQL devuelve días enteros: DATE '2026-04-13' - DATE '2026-03-14' da 30. SQLite resta valores numéricos de día: julianday('2026-04-13') - julianday('2026-03-14') da 30.0. SQL Server utiliza DATEDIFF(day, start, end); MySQL utiliza DATEDIFF(end, start).
Para marcas de fecha y hora del 14 de marzo desde las 09:30 hasta las 18:00, la resta de PostgreSQL da un intervalo de 08:30:00; EXTRACT(EPOCH FROM interval) / 3600 lo expresa como 8,5 horas. Desde SQLite 3.38 se puede escribir:
(unixepoch('2026-03-14 18:00') -
unixepoch('2026-03-14 09:30')) / 3600.0
Esto da 8.5. Una diferencia de días julianos multiplicada por 24 puede dar 8.49999999627471 por la aproximación de coma flotante; redondea para mostrarla. Una duración con parte fraccionaria entre marcas de fecha y hora no debe convertirse a INTEGER antes de calcular la unidad deseada.
Cuenta los cumpleaños cumplidos
Una persona nacida el 2 de noviembre de 1990 tiene 35 años el 21 de octubre de 2026. Los números de año difieren en 36, pero el cumpleaños aún no ha llegado. PostgreSQL utiliza EXTRACT(YEAR FROM AGE(DATE '2026-10-21', DATE '1990-11-02')), que da 35.
SQLite resta uno si el cumpleaños de este año aún está por llegar:
strftime('%Y', '2026-10-21') - strftime('%Y', birth_date)
- (strftime('%m-%d', '2026-10-21') < strftime('%m-%d', birth_date))
La comparación produce 1 cuando el cumpleaños aún no ha llegado y 0 en caso contrario. Dividir los días transcurridos por 365 no es fiable: el 1 de noviembre de 2026, esta persona ha vivido 13 148 días, que divididos por 365 dan 36,02, aunque cumple 36 años mañana. DATEDIFF de SQL Server cuenta límites: pasar del 31 de diciembre al 1 de enero cuenta como un cambio de año, no como un año cumplido de edad.
Incluye todas las marcas de fecha y hora de un período
BETWEEN incluye ambos extremos. Para columnas DATE, del 1 al 31 de marzo abarca marzo. Para marcas de fecha y hora, un límite superior de '2026-03-31' significa medianoche al inicio del último día y deja fuera el resto de ese día.
WHERE ordered_at >= '2026-03-01'
AND ordered_at < '2026-04-01'
Este intervalo semiabierto incluye el inicio y excluye el inicio del período siguiente, abarcando todas las horas de marzo sin elegir una última fracción de segundo.
Las fechas vencidas cumplen due_date < CURRENT_DATE. El límite inferior para los últimos 30 días en PostgreSQL es CURRENT_DATE - 30; en SQLite es date('now', '-30 days'). Los días hasta un vencimiento son due_date - CURRENT_DATE para valores DATE de PostgreSQL y julianday(due_date) - julianday(date('now')) en SQLite.
Puntos clave
- Utiliza funciones de cálculo con fechas o fechas con tipo, en lugar de operaciones aritméticas sobre texto de fecha en SQLite.
- Decide cómo debe tratar la suma de un mes un día que no exista en el mes siguiente.
- Las diferencias de DATE cuentan días; las diferencias entre marcas de fecha y hora pueden incluir fracciones.
- La edad cuenta cumpleaños cumplidos, no días transcurridos divididos por 365.
- Un intervalo semiabierto de marcas de fecha y hora incluye el inicio del período y excluye el siguiente inicio.
- Utiliza un valor actual que solo contenga la fecha para calcular plazos en días enteros.
5Clasifica filas con expresiones CASE
Un informe suele necesitar una regla que convierta datos en una etiqueta o un cargo: un pedido pequeño, un envío pendiente o una posición de prioridad. CASE expresa esa elección dentro de una consulta. Seguirás qué condición se aplica, situarás los valores límite exactos y los ausentes en la categoría adecuada y convertirás códigos en etiquetas con CASE simple. El informe final combina la clasificación con operaciones aritméticas, texto, fechas y valores de sustitución, comprobando cada salida con filas conocidas.
5.1 Clasifica filas en categorías con CASE de búsqueda
Una expresión CASE elige un resultado para cada fila. Puedes utilizarla para etiquetar un intervalo de precios, calcular un cargo o marcar un registro que requiera atención.
Lee la forma de búsqueda
CASE
WHEN total < 50 THEN 'small'
WHEN total < 200 THEN 'medium'
ELSE 'large'
END AS size_band
Cada WHEN proporciona una condición y THEN proporciona el valor que se devuelve si esa condición es TRUE. La base de datos comprueba de arriba abajo y toma la primera condición verdadera. END cierra la expresión; después puede aparecer un alias. Si ninguna condición es TRUE y no hay ELSE, el resultado es NULL.
Un total de 35 cumple la primera condición y pasa a ser 'small'. Un total de 50 no cumple la primera, pero sí la segunda, y pasa a ser 'medium'. Lo mismo ocurre con 199,99. Un total de 200 llega a ELSE y pasa a ser 'large'.
Ajusta el orden y los límites a la regla
La segunda rama no necesita total >= 50: un valor inferior a 50 ya ha obtenido su resultado en la primera rama. Los umbrales < en orden ascendente funcionan porque las ramas anteriores descartan los valores menores. Los umbrales >= en orden descendente pueden funcionar por la misma razón.
Colocar WHEN total < 200 primero hace que nunca se alcance una rama posterior < 50. Un total de 35 ya cumple < 200, por lo que se detiene ahí. CASE no elige la condición más específica ni comprueba qué etiqueta parece mejor.
Compara la regla de negocio con cada extremo. < 50 coloca exactamente 50 en la categoría mediana; <= 50 lo coloca en la pequeña. Comprueba 49,99, 50, 199,99 y 200 para ver ambos lados y los límites. Si las condiciones se escriben como intervalos explícitos, ajusta sus extremos para que no haya huecos ni solapamientos no deseados.
Gestiona NULL antes de los intervalos ordinarios
Un total NULL hace que ambas comparaciones sean UNKNOWN. Por tanto, en la primera expresión llega a ELSE y pasa a ser 'large', lo que resulta engañoso. Detecta primero la ausencia:
CASE
WHEN total IS NULL THEN 'unknown'
WHEN total < 50 THEN 'small'
WHEN total < 200 THEN 'medium'
ELSE 'large'
END
ELSE significa «ninguna condición fue verdadera», por lo que puede recoger entradas ausentes además de valores conocidos fuera de los intervalos comprobados.
Devuelve valores de un tipo uniforme
PostgreSQL necesita tipos THEN y ELSE compatibles. CASE WHEN quantity > 0 THEN unit_price ELSE 'n/a' END falla si unit_price es numérico, porque 'n/a' no se puede convertir en un número. Utiliza NULL para un resultado numérico no disponible o convierte el precio en texto si toda la salida es una etiqueta para mostrar. SQLite permite tipos de resultado mezclados, lo que puede complicar los cálculos posteriores.
Una condición puede combinar columnas:
CASE
WHEN country = 'US' AND subtotal >= 100 THEN 0
ELSE 7.99
END AS shipping_fee
El cargo devuelto puede aparecer dentro de subtotal + CASE ... END AS amount_due. Un CASE es una expresión de valor, no una orden que modifica varias columnas; cada columna del resultado necesita su propia expresión.
CASE también puede proteger una división por fila: CASE WHEN visits = 0 THEN NULL ELSE orders * 100.0 / visits END. Una fila con cero selecciona la rama NULL. orders * 100.0 / NULLIF(visits, 0) expresa de forma más breve la misma regla para una tasa ausente.
Puntos clave
- CASE devuelve el valor de la primera condición que sea TRUE.
- Ordena las condiciones de intervalos solapados para que una comprobación amplia no oculte otra más restringida.
- Elige < o <= para colocar un límite exacto en la categoría prevista.
- Comprueba NULL explícitamente antes de un intervalo cuando ELSE no deba asignarle una etiqueta.
- Mantén compatibles los tipos de resultado y utiliza CASE donde pueda aparecer una expresión de valor.
5.2 Utiliza CASE simple y aplica CASE en distintas partes de una consulta
La forma CASE simple convierte un valor en otro. CASE de búsqueda comprueba condiciones; CASE simple compara la misma expresión con una serie de valores.
Convierte códigos en etiquetas con CASE simple
CASE status
WHEN 'S' THEN 'Shipped'
WHEN 'P' THEN 'Pending'
WHEN 'C' THEN 'Canceled'
ELSE 'Other'
END AS status_label
Las comprobaciones implícitas son status = 'S', después status = 'P' y después status = 'C'. Un estado fuera de estos códigos recibe 'Other'. La forma de búsqueda puede escribir explícitamente las mismas comprobaciones de igualdad. Elige CASE de búsqueda para intervalos, patrones LIKE, comprobaciones de NULL o condiciones que abarquen varias columnas.
CASE region WHEN NULL THEN 'missing' ELSE region END no puede detectar una región NULL. Su comparación implícita region = NULL es UNKNOWN, por lo que la fila llega a ELSE y sigue siendo NULL. Escribe CASE WHEN region IS NULL THEN 'missing' ELSE region END.
Asigna una posición de ordenación personalizada
El orden alfabético de las prioridades es high, low, medium. Para ordenar por urgencia, convierte las etiquetas en números:
SELECT ticket_id, priority
FROM tickets
ORDER BY CASE priority
WHEN 'high' THEN 1
WHEN 'medium' THEN 2
WHEN 'low' THEN 3
ELSE 4
END;
Ahora el orden ascendente coloca high antes de medium y después low, con los demás valores o los ausentes al final. CASE es una expresión de ordenación; no tiene que ser una columna mostrada. Utilizar DESC invertiría la clasificación numérica.
Crea un indicador numérico
CASE WHEN discount_pct > 0 THEN 1 ELSE 0 END AS is_discounted
Un porcentaje positivo recibe 1; un cero conocido recibe 0. Un porcentaje NULL también recibe 0 porque > 0 es UNKNOWN y ELSE lo recoge. Por tanto, este indicador significa «hay un descuento positivo registrado». No conserva la distinción entre ausencia de descuento y descuento desconocido. Si necesitas esa distinción, añade una rama IS NULL con su propio resultado.
Los indicadores se pueden seleccionar, ordenar, filtrar o incluir en operaciones aritméticas. En una cláusula WHERE que deba funcionar en distintas bases de datos, repite la expresión o utiliza su condición original en lugar de referirte a un alias de salida recién definido.
Reconoce las funciones condicionales relacionadas
COALESCE(bonus, 0) es una forma abreviada de CASE WHEN bonus IS NOT NULL THEN bonus ELSE 0 END. NULLIF(a, b) corresponde a CASE WHEN a = b THEN NULL ELSE a END. Sus nombres comunican directamente estos usos habituales.
SQLite desde la versión 3.32 y SQL Server tienen IIF(condition, true_value, false_value); MySQL tiene IF. DECODE de Oracle convierte coincidencias de igualdad, por ejemplo, DECODE(status, 'S', 'Shipped', 'P', 'Pending', 'Other'). DECODE trata dos NULL como iguales, a diferencia de las comparaciones de igualdad de CASE simple. CASE estándar funciona en todos estos sistemas.
Un CASE puede contener otro CASE, pero las condiciones combinadas suelen hacer más clara una expresión sin anidar. Una regla de envío puede indicar directamente WHEN country = 'US' AND subtotal >= 100 THEN 0, manteniendo juntas las comprobaciones de país y subtotal.
Puntos clave
- CASE simple compara una expresión mediante igualdad con una serie de valores.
- Utiliza CASE de búsqueda para comprobaciones de NULL, intervalos y condiciones combinadas.
- Un CASE numérico en ORDER BY crea una clasificación personalizada.
- Un indicador con ELSE 0 también asigna cero cuando su condición es UNKNOWN.
- COALESCE y NULLIF expresan casos particulares habituales de CASE.
- DECODE de Oracle trata dos NULL como iguales; CASE simple no lo hace.
5.3 Combina funciones en una consulta completa para informes
Un informe puede limpiar nombres, calcular totales netos, identificar meses y etiquetar la rapidez del envío en un solo SELECT. Construye cada expresión a partir de sus entradas y comprueba el resultado antes de combinarla con las demás.
Trabaja a partir de filas conocidas
Una tabla de pedidos contiene estos registros. Las fechas son texto ISO para la consulta SQLite que aparece a continuación; quantity es entero y unit_price es numérico.
| Pedido | Cliente | Cantidad | Precio | Descuento % | Fecha del pedido | Fecha de envío |
|---|---|---|---|---|---|---|
| 1001 | Ana Lopez | 3 | 12,50 | 10 | 2026-03-14 | 2026-03-17 |
| 1002 | Ben Okafor | 1 | 240,00 | 0 | 2026-03-30 | NULL |
| 1003 | Chen Wu | 12 | 4,25 | NULL | 2026-04-02 | 2026-04-03 |
Aquí, un descuento ausente significa que no hay descuento. Empieza recuperando los campos originales. Añade una columna calculada cada vez y utiliza LIMIT 5 mientras compruebas una muestra pequeña.
Sigue un cálculo anidado
ROUND(quantity * unit_price *
(1 - COALESCE(discount_pct, 0) / 100.0), 2)
COALESCE proporciona primero un descuento conocido. Dividir por 100.0 conserva su parte fraccionaria. Restarlo de 1 da la fracción que se paga, la multiplicación da el importe neto y ROUND establece la precisión final. El importe de Ana es 33,75, el de Ben es 240,0 y el de Chen es 51,0. El descuento NULL de Chen se convierte en cero; en cambio, una fecha de envío ausente debe seguir ausente en el recuento de días.
Construye el informe de SQLite
SELECT order_id,
first_name || ' ' || last_name AS customer,
ROUND(quantity * unit_price *
(1 - COALESCE(discount_pct, 0) / 100.0), 2) AS net_total,
strftime('%Y-%m', order_date) AS order_month,
CAST(julianday(shipped_date) - julianday(order_date)
AS INTEGER) AS days_to_ship,
CASE
WHEN shipped_date IS NULL THEN 'not shipped'
-- fast = shipped within 2 days
WHEN julianday(shipped_date) - julianday(order_date) <= 2
THEN 'fast'
ELSE 'standard'
END AS shipping
FROM orders
ORDER BY order_id;
Cada expresión tiene un alias de salida claro. La diferencia numérica de días se convierte a INTEGER porque estos valores solo contienen fechas. La rama IS NULL aparece antes de la comparación de rapidez, por lo que un pedido sin enviar recibe una etiqueta útil.
La salida es:
| Pedido | Cliente | Total neto | Mes | Días | Envío |
|---|---|---|---|---|---|
| 1001 | Ana Lopez | 33,75 | 2026-03 | 3 | estándar |
| 1002 | Ben Okafor | 240,0 | 2026-03 | NULL | sin enviar |
| 1003 | Chen Wu | 51,0 | 2026-04 | 1 | rápido |
Adapta los tipos y las cláusulas de la consulta
Para columnas DATE de PostgreSQL, utiliza TO_CHAR(order_date, 'YYYY-MM') para el mes y shipped_date - order_date para el recuento de días y la comparación CASE. Mantén unit_price como numeric exacto para ROUND de dos argumentos. La concatenación, la sustitución del descuento y la regla de clasificación conservan el mismo significado.
Para filtrar los totales redondeados superiores a 50 en ambas bases de datos, repite la expresión neta completa en WHERE. Permanecen los pedidos 1002 y 1003. SQLite también permite WHERE net_total > 50, pero PostgreSQL no puede ver ese nuevo alias en la etapa de filtrado. ORDER BY net_total DESC funciona en ambos.
Al trasladar un informe, comprueba los tipos y los nombres de funciones de cada expresión. Una función de texto debe recibir texto, un cálculo de fechas debe recibir un valor de fecha compatible y una sustitución numérica debe expresar la regla prevista. Coloca cada salida en su propia línea; un comentario breve puede definir un umbral de negocio sin dificultar la lectura del SQL.
Puntos clave
- Construye y comprueba una columna calculada cada vez con una muestra pequeña.
- Las funciones anidadas pasan sus resultados hacia fuera; mantén adecuado el tipo de cada entrada.
- Un descuento ausente y una fecha de envío ausente pueden necesitar tratamientos distintos.
- Utiliza expresiones de fecha adecuadas al dialecto y conserva las reglas del informe.
- Filtra con la expresión completa y ordena con su alias de salida cuando corresponda.
Ejemplos de Columnas calculadas en SQL
1Construye y comprueba un importe de línea con descuento
16 pasos
- 1IntroducciónConvierte una fila en un importe útil
Una línea de pedido registra ocho artículos a 7,50 cada uno con un descuento del 20 por ciento. El informe necesita un importe neto, pero la tabla solo almacena las entradas. Construirás la expresión por etapas, darás nombre a su salida y comprobarás qué hace la división entera con el descuento.
Los ejemplos utilizan SQLite y PostgreSQL. Cuando sus reglas de tipos difieren, el nombre de la base de datos identifica el resultado.
- 2ExplicaciónEmpieza con una expresión
Una expresión combina valores para producir otro valor. Aquí,
quantity * unit_priceutiliza dos columnas de la fila actual.SELECT quantity * unit_price AS gross_total FROM order_lines;gross_totales el alias de salida. Para la fila de ejemplo, el nuevo valor es60.0en SQLite. Cada una de las demás filas aporta sus propias entradas; la consulta no guarda estos totales en la tabla. - 3ConexiónCada fila sigue teniendo su propio valor
Una función de una sola fila devuelve un valor por cada fila de entrada.
ROUND(unit_price, 0)cambia el precio mostrado de una fila, mientras queUPPER(item_name)cambia su texto mostrado.Estas funciones no combinan las líneas de pedido. Una función de agregación como SUM sí combina valores de un grupo, por lo que responde a otro tipo de pregunta. Un cálculo en SELECT puede conservar el detalle de los pedidos individuales.
- 4ConsejoDa un nombre claro al resultado
AS net_totales un alias sencillo y legible. Utiliza comillas dobles cuando un nombre tenga un espacio, como enAS "Net Total". Las comillas simples identifican valores de texto.Mantén una coma entre las expresiones de salida.
SELECT quantity unit_pricedevuelve una columna de cantidades con el encabezado unit_price: sin coma, el segundo nombre se convierte en un alias. Esa consulta puede ejecutarse correctamente y mostrar menos columnas de las previstas. - 5DesafíoColoca el alias en la consulta
La tabla solo tiene quantity y unit_price. Una consulta define
quantity * unit_price AS gross_total. ¿Puede un filtro WHERE de PostgreSQL utilizargross_total > 50y puede ORDER BY utilizargross_total DESC?---reveal---
WHERE no puede ver ese nuevo alias porque precede lógicamente a SELECT. Repite
quantity * unit_price > 50. ORDER BY va después de SELECT y puede utilizargross_total DESC. SQLite permite el alias en WHERE como una extensión, pero PostgreSQL no. - 6EjemploConvierte un descuento en la fracción que se paga
El importe bruto es
8 * 7.50, es decir, 60. Un descuento del 20 por ciento deja un 80 por ciento por pagar. Exprésalo como1 - discount_pct / 100.0.quantity * unit_price * (1 - discount_pct / 100.0)La división da
0.2; los paréntesis dan0.8; la multiplicación da un importe neto de48.0. Los paréntesis mantienen la resta como un único factor. - 7Idea claveUn decimal posterior no puede reparar una división anterior
Supón que discount_pct es un entero y que el divisor se escribe como
100. SQLite y PostgreSQL calculan20 / 100mediante división entera y obtienen 0. El factor pasa a ser 1, por lo que el neto se mantiene incorrectamente en 60.El precio decimal de otra parte de la expresión no corrige esa división interna. Utiliza
100.0en la propia división. Convertir después el cociente ya calculado cambia su tipo, pero no puede recuperar la parte fraccionaria perdida. - 8DesafíoEncuentra el cálculo que perdió su parte fraccionaria
Una fila de SQLite tiene el entero completed = 9 y el entero assigned = 12. ¿Qué devuelve
completed / assigned * 100.0y cómo debería calcular el porcentaje la expresión?---reveal---
Devuelve
0.0: la división entera9 / 12se convierte primero en 0. Escribecompleted * 100.0 / assigned, que da75.0. La conversión debe producirse antes de dividir, no solo antes de mostrar el resultado final. - 9ExplicaciónElige la regla para obtener un entero
ROUND elige un valor redondeado cercano. FLOOR baja hasta un entero, CEIL sube y TRUNC elimina la parte fraccionaria hacia cero.
Para
-6.4, FLOOR da-7, mientras que CEIL y TRUNC dan-6. La dirección importa con las entradas negativas. PostgreSQL proporciona estas funciones; CEIL, FLOOR y TRUNC de SQLite requieren una versión compilada con funciones matemáticas. ABS, que da la distancia a cero, está incorporada en SQLite. - 10ConsejoComprueba el tipo numérico antes de redondear
En PostgreSQL, ROUND de dos argumentos recibe
numeric, no double precision. Para una columna de coma flotante, escribeROUND(CAST(amount AS numeric), 2). SQLite acepta su propia forma numérica de ROUND.Los valores aproximados de coma flotante pueden producir empates inesperados. Para importes exactos, NUMERIC/DECIMAL de PostgreSQL almacena decimales exactos; SQLite puede conservar los céntimos enteros como números enteros. Redondea el resultado mostrado después del cálculo.
- 11ExplicaciónHaz explícito un cambio de tipo
CAST(expression AS type)solicita una conversión. El texto'28'puede convertirse en el entero 28 conCAST('28' AS INTEGER). El número puede convertirse en texto conCAST(28 AS TEXT).Para una división con parte fraccionaria, SQLite necesita REAL para obtener de forma fiable un operando no entero.
CAST(7 AS NUMERIC)puede seguir siendo el entero 7 en ese sistema. NUMERIC de PostgreSQL proporciona un tipo decimal exacto. Convertir NULL con CAST sigue dando NULL. - 12EjemploMantén separados los identificadores y las cantidades
Supón que una etiqueta almacena el código postal estadounidense ZIP
'00421'. Convertirlo en un entero da421, y se pierden los ceros iniciales. Es un identificador, por lo que no se trata de hacer operaciones aritméticas.Una columna de texto que realmente contenga cantidades puede necesitar una conversión para la ordenación numérica. Los textos
'12','3'y'80'se ordenan en ese orden; la ordenación numérica da 3, 12, 80. Elige la conversión según el significado de la columna. - 13DesafíoInterpreta una conversión sin tomarla como validación
SQLite ejecuta correctamente
CAST('31units' AS INTEGER). ¿Qué valor devuelve y demuestra ese éxito que el texto original era un entero válido?---reveal---
Devuelve 31 leyendo la parte numérica inicial. Ejecutarse correctamente no valida toda la cadena. PostgreSQL rechaza ese mismo texto como entero. SQLite también puede convertir en cero texto sin un prefijo numérico, ocultando una entrada incorrecta.
- 14Idea claveLa conversión a entero no funciona igual en todos los sistemas
Para el valor numérico
4.7,CAST(... AS INTEGER)de SQLite trunca a 4, mientras que PostgreSQL redondea a 5. Si un informe quiere «unidades enteras que no superen este valor», exprésalo con FLOOR antes de la conversión.Una conversión implícita también depende de la base de datos. PostgreSQL puede inferir un número a partir de un literal entre comillas en una operación aritmética, pero una columna TEXT necesita una conversión explícita. Los caracteres visibles por sí solos no determinan el tipo del operando.
- 15DesafíoComprueba la expresión neta completa
Para ocho artículos a 7,50 con el entero discount_pct = 20, un informe escribe
ROUND(quantity * unit_price * (1 - discount_pct / 100.0), 2) AS net_total. ¿Cuál es el resultado y puede ese alias ordenar la salida?---reveal---
El bruto es 60, la fracción que se paga es 0,8 y el neto es
48.0en SQLite.ORDER BY net_totales válido tanto en SQLite como en PostgreSQL porque la ordenación puede ver el alias de SELECT. - 16RepasoLee las entradas, el cálculo y el nombre de salida
Un importe calculado sigue un recorrido: la fila aporta valores, las operaciones aritméticas y las funciones producen el resultado y un alias le da nombre. Comprueba el orden de las operaciones y los tipos de los operandos antes de aceptar un número mostrado.
Cuando un resultado sea inesperado, revisa primero una división o conversión interna. Para filtrar un valor calculado en distintas bases de datos, repite su expresión en WHERE; para ordenarlo, utiliza el alias de salida en ORDER BY.
2Sigue los datos ausentes a través de una consulta
12 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónUn importe ausente cambia algo más que una celda
- 2ExplicaciónNULL es una entrada desconocida
- 3EjemploUtiliza una comprobación que detecte la ausencia
- 4Idea claveWHERE solo acepta TRUE
- 5DesafíoCombina una condición conocida con otra desconocida
- 6ConsejoNo dejes NULL en una lista de exclusión
- 7ExplicaciónElige un valor de sustitución según el significado
- 8EjemploMantén uniforme el tipo de presentación
- 9EjemploConvierte un denominador cero en un valor ausente
- 10DesafíoLimpia la cadena vacía antes de aplicar la etiqueta
- 11DesafíoDistingue la decisión de presentación de la decisión de filtrado
- 12RepasoMantén visible el significado de una ausencia
3Limpia un nombre y extrae el dominio de un correo electrónico
14 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónHaz utilizable el texto sin perder sus partes
- 2EjemploAporta el espacio entre el nombre y el apellido
- 3ExplicaciónDecide qué efecto tiene una parte ausente del nombre
- 4EjemploLimpia el correo de dentro hacia fuera
- 5DesafíoElige entre recortar y sustituir
- 6ConsejoComprueba las reglas de caracteres y dialectos
- 7ExplicaciónCuenta desde uno
- 8EjemploLocaliza el separador
- 9EjemploExtrae los caracteres anteriores y posteriores a @
- 10DesafíoEncuentra el resultado desplazado una posición
- 11Idea claveUn resultado de búsqueda cero necesita su propio tratamiento
- 12ConsejoExtrae finales y rellena códigos en el dialecto adecuado
- 13DesafíoCombina la limpieza con la extracción
- 14RepasoSigue los caracteres exactos
4Crea etiquetas de fecha y filtros de período fiables
18 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónSepara el valor de calendario de su etiqueta
- 2ExplicaciónElige una representación de fecha clara
- 3EjemploLee un formato local fijo
- 4DesafíoExplica qué texto se ordena por fecha
- 5ConsejoComprueba la interpretación y la referencia horaria actual
- 6EjemploExtrae el mes con el tipo de retorno correcto
- 7ExplicaciónConserva el año en la etiqueta de año y mes
- 8EjemploCrea una presentación sin cambiar la ordenación
- 9DesafíoEncuentra el trimestre correcto
- 10ConexiónElige la convención de numeración de los días de la semana
- 11EjemploAñade diez días a la reserva
- 12Idea claveUn mes no es un número fijo de días
- 13EjemploMide días y horas en unidades adecuadas
- 14DesafíoIncluye la última tarde del mes
- 15ExplicaciónCuenta los cumpleaños que ya han llegado
- 16ConsejoInterpreta las fechas relativas como límites móviles
- 17DesafíoCombina un vencimiento con la selección de un mes
- 18RepasoComprueba el tipo, la regla de calendario y los extremos
5Etiqueta pedidos y construye el informe final
17 pasos
Guarda esta unidad para seguir cada Lección Interactiva paso a paso.
- 1IntroducciónAsigna una etiqueta útil a cada pedido
- 2ExplicaciónElige la primera condición verdadera
- 3EjemploSigue el límite exacto
- 4Idea claveELSE también puede recoger un importe desconocido
- 5DesafíoRecupera una categoría pequeña oculta
- 6ConsejoDevuelve resultados compatibles
- 7EjemploConvierte un valor de estado en una etiqueta
- 8Desafío¿Por qué WHEN NULL no detecta la fila?
- 9EjemploOrdena las prioridades por posición
- 10Idea claveUn indicador puede reunir casos conocidos y desconocidos
- 11EjemploEmpieza el informe con entradas conocidas
- 12EjemploCalcula primero el importe neto
- 13EjemploAñade fechas con una regla de ausencia independiente
- 14DesafíoComprueba una segunda fila con ambas reglas
- 15ConexiónAdapta las expresiones de fecha a PostgreSQL
- 16DesafíoFiltra el importe que muestra realmente el informe
- 17RepasoComprueba el informe como un conjunto de decisiones explícitas
Ejercicios de Columnas calculadas en SQL
Set 1: Limpia texto y trabaja con valores de calendario10 Preguntas de Práctica
Pregunta 1 de 10
LOWER(TRIM(' RAE@Mail.COM ')) en SQLite?Mostrar respuestaOcultar respuesta
'rae@mail.com'. Conservar el espacio final significaría que solo se recortó el extremo izquierdo; TRIM ordinario trata ambos extremos y no necesita un RTRIM aparte.Pregunta 2 de 10
first_name = 'Mira', middle_name = NULL y last_name = 'Shah'. ¿Qué devuelven first_name || ' ' || middle_name || ' ' || last_name y CONCAT_WS(' ', first_name, middle_name, last_name), en ese orden?Mostrar respuestaOcultar respuesta
|| propaga su entrada NULL del segundo nombre, haciendo que todo el nombre sea NULL. CONCAT_WS omite la parte ausente y coloca un separador entre Mira y Shah. Habría dos espacios si se conservara una posición vacía para el segundo nombre, pero aquí la entrada es NULL y CONCAT_WS la omite.Pregunta 3 de 10
SUBSTR('Seattle', 3, 3)?Mostrar respuestaOcultar respuesta
'att'. El fragmento 'eat' empieza en la posición 2 y se obtendría al interpretar la posición inicial indicada como un carácter anterior a la que realmente es.Pregunta 4 de 10
email puede contener NULL o texto sin @. Para el texto que contenga @, devuelve todo lo que haya después del primer @; en caso contrario, devuelve NULL. ¿Qué expresión es adecuada?Mostrar respuestaOcultar respuesta
>= 0 también acepta un separador ausente, cuya posición es cero, y devolvería toda la cadena mal formada.Pregunta 5 de 10
Mostrar respuestaOcultar respuesta
'2027-11-06'. La terminación invertida 06-11 representa el 11 de junio, mientras que un día final de un dígito no sigue el formato de anchura fija.Pregunta 6 de 10
date('2027-04-31')?Mostrar respuestaOcultar respuesta
'2027-05-01'. Por tanto, un resultado de fecha que no sea NULL no garantiza que el día original existiera en ese mes. PostgreSQL rechaza el literal DATE con tipo equivalente, pero no se debe suponer ese comportamiento estricto para la función de fecha de SQLite.Pregunta 7 de 10
d contiene '2027-08-19'. ¿Cuáles son los resultados de strftime('%m', d) = 8 y CAST(strftime('%m', d) AS INTEGER) = 8, en ese orden?Mostrar respuestaOcultar respuesta
'08', que no es igual al número 8 en la primera expresión. Convertir ese texto a INTEGER produce 8 y hace verdadera la segunda comparación. El cero inicial forma parte del texto devuelto; mostrar un mes como dígitos no hace numérico el resultado de la función.Pregunta 8 de 10
event_date, abarca varios años. Un informe muestra fechas como MM/DD/YYYY y debe mantener el orden cronológico. ¿Cómo debe seleccionar y ordenar la columna?Mostrar respuestaOcultar respuesta
Pregunta 9 de 10
d de SQLite es '2027-04-24'. ¿Qué devuelve date(d, '+10 days')?Mostrar respuestaOcultar respuesta
'2027-05-04'. El 3 de mayo cuenta la fecha inicial como uno de los diez días añadidos. Un desplazamiento de fecha mide días posteriores al punto de partida y lleva los días restantes al mes siguiente.Pregunta 10 de 10
Mostrar respuestaOcultar respuesta
Set 2: Calcula importes y gestiona datos ausentes10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
units y unit_cost. ¿Qué lista SELECT devuelve su producto con el encabezado extended_cost?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
lines solo contiene units y price. Una consulta debe ejecutarse en SQLite y PostgreSQL. ¿Cómo debe conservar las filas cuyo producto sea superior a 90 y ordenar primero el producto mayor?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
SELECT 14 + 5 * 3; en SQLite?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
old_count y new_count son enteros que contienen 60 y 69. ¿Cuál es el resultado de (new_count - old_count) / old_count * 100?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
units = 5 y discount_pct = 12, con price = 18.0. ¿Qué resultado produce ROUND(units * price * (1 - discount_pct / 100), 2)?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
CAST('27boxes' AS INTEGER)?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
delivery_date registrada?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
region: 'East', 'West', NULL y 'North'. ¿Cuántas filas cumplen WHERE NOT (region = 'East')?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
'unlisted' en SQLite. ¿Qué expresión lo hace conservando los números registrados?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
sales y visits. Una tasa debe conservar los porcentajes con parte fraccionaria y seguir siendo NULL cuando visits sea cero. No debe inventar una tasa de cero. ¿Qué expresión es adecuada?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 3: Clasifica filas y diagnostica la lógica de los informes10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
score = 75: CASE WHEN score < 60 THEN 'review' WHEN score < 80 THEN 'ready' ELSE 'strong' END?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
CASE WHEN amount < 500 THEN 'regular' WHEN amount < 100 THEN 'small' ELSE 'large' END nunca devuelve 'small' para importes que no son NULL?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
balance numérico puede ser NULL. Las etiquetas requeridas son 'unknown' si falta, 'credit' por debajo de 0, 'settled' en 0 y 'due' por encima de 0. ¿Qué CASE cumple todas las reglas?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
state de 'H' significa retenido y 'R' significa liberado. ¿Qué devuelve CASE state WHEN 'H' THEN 'held' WHEN 'R' THEN 'released' ELSE 'other' END para 'R'?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
'urgent', 'normal' y 'deferred' en ese orden, con todas las demás prioridades o las NULL al final. ¿Qué expresión ORDER BY es adecuada?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
qty = 4, price = 15.0, discount_pct = NULL y shipped_date = NULL. Un descuento ausente significa que no hay descuento. ¿Qué par se obtiene de ROUND(qty * price * (1 - COALESCE(discount_pct, 0) / 100.0), 2) y CASE WHEN shipped_date IS NULL THEN 'open' ELSE 'sent' END?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
LOWER(TRIM(customer)) AS name y date(due_date, '+7 days') AS reminder_date. El valor original de customer es ' IVAN ' y due_date es '2027-09-26'. ¿Qué par de salida debe encontrar una comprobación de una muestra?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
x 2, 7, NULL y 11. ¿Cuántas filas devuelven WHERE x NOT IN (2, NULL) y WHERE x <> 2 OR x IS NULL, respectivamente?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
'1998-12-18'. A fecha de '2027-12-17', ¿cuál es su edad en años cumplidos y por qué puede ser incorrecto restar los dos números de año?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
rating, puede ser NULL. Una columna de presentación debe mostrar la valoración como texto o 'unrated'. ¿Qué expresión es adecuada?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Set 4: Comprueba informes completos y límites difíciles10 Preguntas de Práctica
Guarda esta unidad para ver todas las respuestas y practicar cada set.
Pregunta 1 de 10
qty entero, price NUMERIC y discount_pct entero. Un descuento ausente significa que no hay descuento. Un informe debe conservar los totales netos redondeados superiores a 75 y ordenarlos de mayor a menor. ¿Qué consulta completa es adecuada?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 2 de 10
reading, es DOUBLE PRECISION. ¿Cómo puede un informe redondearla a dos decimales sin un error de firma de función?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 3 de 10
COALESCE(NULL, '', 'backup') en SQLite?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 4 de 10
email = 'nora@research.org'. ¿Qué resultado produce SUBSTR(email, INSTR(email, '@'))?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 5 de 10
'2027-01-31', compara date(d, '+1 month') de SQLite desde la versión 3.46, date(d, '+1 month', 'floor') de SQLite y DATE '2027-01-31' + INTERVAL '1 month' de PostgreSQL. ¿Qué fechas de calendario resultan, en ese orden?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 6 de 10
stock, puede ser NULL. El indicador numérico requerido es NULL para existencias desconocidas, 1 para existencias inferiores a 5 y 0 en los demás casos. ¿Qué expresión es adecuada?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 7 de 10
'2027-05-08 10:15:00' hasta '2027-05-08 13:45:00'. ¿Qué devuelve (unixepoch(end_time) - unixepoch(start_time)) / 3600.0?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 8 de 10
qty = 6, price = 8.0, discount_pct = 25, fecha de pedido '2027-07-10' y fecha de envío '2027-07-12'. El neto utiliza ROUND(qty * price * (1 - COALESCE(discount_pct, 0) / 100.0), 2). Un CASE etiqueta el envío NULL como 'open', los días transcurridos <= 2 como 'fast' y los demás como 'standard'. ¿Qué neto y etiqueta resultan?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 9 de 10
d. ¿Cómo puede calcular el trimestre para todos los meses?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
Pregunta 10 de 10
(qty 3, price 22.0, discount_pct NULL), B (qty 4, price 20.0, discount_pct 25) y C (qty 2, price 40.0, discount_pct 10). Un descuento ausente significa que no hay descuento. Calcula ROUND(qty * price * (1 - COALESCE(discount_pct, 0) / 100.0), 2) AS net, conserva net > 60 utilizando la expresión completa en WHERE y ordena por net DESC. ¿Cuál es el orden de las filas?Mostrar respuestaOcultar respuesta
Guarda esta unidad para ver esta respuesta.
¿Te atascas con una pregunta tuya? Ayuda con Tareas
Términos Clave
A
Afinidad de tipo
Alias de columna
AS line_total y puede ordenarlo con ORDER BY line_total.Anidamiento de funciones
ROUND(COALESCE(amount, 0), 2), la sustitución se resuelve antes de que la función de redondeo reciba su entrada.C
Cadena de caracteres
' New York ' incluye espacios en los extremos y dos espacios interiores que afectan a su longitud.CASE de búsqueda
CASE WHEN total < 50 THEN 'small' ELSE 'large' END elige una etiqueta a partir del importe de la fila.CASE simple
CASE status WHEN 'S' THEN 'Shipped' ELSE 'Other' END convierte un código de estado almacenado en una etiqueta.CEIL
CEIL(4.1) da 5 porque cuatro está por debajo de la entrada y cinco es el siguiente número entero.COALESCE
COALESCE(mobile_phone, home_phone, 'no phone') utiliza el número fijo si falta el número de móvil.Columna calculada
quantity * unit_price AS line_total aunque la tabla no tenga una columna line_total.Comparación segura frente a NULL
NULL IS NOT DISTINCT FROM NULL es TRUE en PostgreSQL y en SQLite desde la versión 3.39.Comprobación de una muestra
LIMIT 5 mientras construyes el informe facilita localizar un espacio ausente o un error de división entera.Concatenación
first_name || ' ' || last_name inserta un espacio entre las dos partes del nombre registradas.Consulta para informes
Conversión entre mayúsculas y minúsculas
LOWER(TRIM(email)) uniforma una dirección de correo ASCII limpia para compararla normalizando las mayúsculas y minúsculas.Conversión explícita
CAST(quantity AS REAL) / 4 cambia el operando de SQLite antes de que la división pueda perder una parte fraccionaria.Conversión implícita
'Order #' || 42, produciendo la etiqueta 'Order #42'.D
DATE
DATE '2026-03-14' indica explícitamente el 14 de marzo de 2026 como un valor de fecha de PostgreSQL.División entera
7 / 2 produce 3; convertir el segundo operando en 2.0 conserva la parte fraccionaria y produce 3,5.E
Edad en años cumplidos
Etiqueta de año y mes
'2026-03' mantiene marzo de 2026 separado de marzo de 2025 en la presentación de un informe.Expresión
quantity * unit_price es una expresión que produce el importe de la línea para cada fila.EXTRACT
EXTRACT(MONTH FROM DATE '2026-03-14') de PostgreSQL devuelve el valor numérico de mes 3.F
FLOOR
FLOOR(-4.1) da -5, por lo que se diferencia de eliminar simplemente la parte fraccionaria.Formato de fecha ISO
'2026-03-14' tiene ceros iniciales y se ordena antes de '2026-11-02' en orden cronológico.Función de una sola fila
UPPER(city) en SELECT cambia el texto de ciudad mostrado para cada cliente devuelto por la consulta.I
Indicador numérico
CASE WHEN discount_pct > 0 THEN 1 ELSE 0 END asigna cero tanto a los descuentos ausentes como a los no positivos.INSTR
INSTR('ana@example.com', '@') da 4, mientras que una cadena sin @ produce cero.Intercalación
'Boston' = 'boston' sea verdadero cuando SQLite con su configuración predeterminada no lo hace.Intervalo
INTERVAL '1 month' a un DATE de PostgreSQL devuelve una marca de fecha y hora y sigue su regla de final de mes.Intervalo semiabierto
ordered_at >= '2026-03-01' AND ordered_at < '2026-04-01' incluye todas las marcas de fecha y hora de marzo.IS NULL
WHERE phone IS NULL recupera clientes sin teléfono registrado sin comparar un valor con NULL mediante igualdad.L
LENGTH
LENGTH(' Bo ') da 4 porque cuentan tanto los dos espacios de los extremos como las dos letras.Literal
first_name || ' ' || last_name es un literal de texto proporcionado por la consulta.Lógica trivalente
FALSE AND UNKNOWN es FALSE, pero TRUE AND UNKNOWN sigue siendo UNKNOWN porque el segundo requisito no está resuelto.M
Módulo
135 % 60 da los 15 minutos que sobran después de dos horas completas.N
NULL
salary + bonus sea desconocido aunque el salario del empleado esté registrado.NULLIF
NULLIF(visits, 0) conserva los recuentos positivos de visitas, pero convierte el cero en un divisor ausente para una tasa.Número de coma flotante
0.1 + 0.2 = 0.3 sea falso porque las aproximaciones almacenadas no suman el mismo valor.Número de día juliano
julianday(end_date) - julianday(start_date) en lugar de restar directamente cadenas de fecha ISO.O
Orden lógico de procesamiento de consultas
P
Patrón de formato
'%m/%d/%Y' para una etiqueta de fecha estadounidense; TO_CHAR de PostgreSQL utiliza 'MM/DD/YYYY'.Posición de ordenación personalizada
Posición de un carácter
'ana@example.com' está en la posición 4, por lo que el dominio empieza en la posición 5.Precedencia de operadores
10 + 3 * 2, por lo que el resultado es 16 en lugar de 26.R
Rama WHEN
< 200 puede impedir que se seleccione alguna vez una rama posterior < 50.Relleno
LPAD('42', 5, '0') de PostgreSQL devuelve '00042', dando cinco caracteres a un código corto.REPLACE
REPLACE('555-0100', '-', '') elimina el guion y muestra '5550100' sin modificar la tabla.Resultado alternativo ELSE
ELSE 'large' salvo que una rama anterior compruebe explícitamente total IS NULL.ROUND
ROUND((price - cost) / price * 100, 1) para mostrar un margen con un decimal.S
strftime
strftime('%m', '2026-03-14') devuelve '03', que debe compararse con texto o convertirse antes de un uso numérico.Subcadena
SUBSTR('Boston', 1, 3) devuelve 'Bos', tomando tres caracteres a partir de la primera posición.T
Texto numérico
'10', '100' y '9' aparecen en ese orden de texto ascendente, que difiere del orden numérico.Tiempo Unix
3600.0 para conservar las horas con parte fraccionaria de una duración.TIMESTAMP
'2026-03-31 14:05:00' es posterior a medianoche al inicio del 31 de marzo.Tipo de datos
'42' y el entero 42 pueden parecer iguales en una cuadrícula y comportarse de forma distinta en SQL.TRIM
TRIM(' New York '), los dos espacios entre las palabras permanecen en el texto devuelto.U
UNKNOWN
bonus = NULL es UNKNOWN, por lo que no puede identificar una bonificación ausente en un filtro WHERE.UTC
V
Valor de sustitución
Valor límite
total < 50 es falso; cambiar la comprobación a total <= 50 hace que sea verdadera.Valor marcador
NULLIF(phone, '') convierte una cadena de teléfono vacía en NULL antes de proporcionar una etiqueta de presentación.- 1Modelo relacional
- 2Consultas con SELECT
- 3Columnas calculadas en SQL
- 4Agregación y agrupación en SQL
- 5JOIN SQL
- 6Crear y modificar tablas de base de datos
Sobre esta unidad
Crea tus propios Materiales de Estudio
Convierte tus notas, diapositivas y documentos en Guías de Estudio, Preguntas de Práctica, Flashcards y 6 herramientas más.