Conversión de tipos, división entera y redondeo
BásicoCAST(x AS tipo) convierte un valor a otro tipo; en PostgreSQL también se escribe x::tipo. Es clave al dividir: entre dos enteros, PostgreSQL hace división entera y descarta los decimales (5 / 2 da 2). Convierte uno de los dos a numeric antes de dividir y redondea con round(valor, 2).
Sintaxis
CAST(columna AS numeric)
columna::numeric
round(CAST(a AS numeric) / b, 2)Ejemplo
SELECT
count(*) AS pedidos,
sum(CASE WHEN o.status = 'cancelled' THEN 1 ELSE 0 END) AS cancelados,
sum(CASE WHEN o.status = 'cancelled' THEN 1 ELSE 0 END) / count(*) AS division_entera,
round(CAST(sum(CASE WHEN o.status = 'cancelled' THEN 1 ELSE 0 END) AS numeric) / count(*), 4) AS proporcion,
round(sum(CASE WHEN o.status = 'cancelled' THEN 1 ELSE 0 END)::numeric * 100 / count(*), 2) AS porcentaje
FROM orders AS o
WHERE o.currency = 'UYU';Resultado
| pedidos | cancelados | division_entera | proporcion | porcentaje |
|---|---|---|---|---|
| 684 | 97 | 0 | 0.1418 | 14.18 |
Cómo leerlo
97 cancelados de 684 pedidos en pesos uruguayos. division_entera da 0 porque los dos operandos son enteros y la parte decimal (0.14) se descarta sin avisar. En las dos columnas siguientes, uno de los operandos se convierte a numeric antes de dividir, y el resultado es 0.1418, es decir, 14.18 %. CAST(… AS numeric) y ::numeric hacen exactamente lo mismo.
Error común
Así no
SELECT round(CAST(97 AS double precision) / 684, 2) AS proporcion;Redondear un double precision (número de punto flotante) con dos decimales. En PostgreSQL round(valor, decimales) solo existe para numeric, y esta consulta falla con «function round(double precision, integer) does not exist». Convierte a numeric (round(x::numeric, 2)), no a float.
En otros motores: MySQL, BigQuery, SQL Server, Snowflake, PostgreSQL
MySQL
/entre enteros devuelve un decimal; la división entera se pide conDIV. EnCAST, el tipo de destino se escribeDECIMAL(p, s)oSIGNED.SELECT 5 / 2; -- 2.5000 SELECT 5 DIV 2; -- 2BigQuery
/entre enteros devuelve un número de punto flotante (FLOAT64), no un entero; entre valoresNUMERICdevuelveNUMERIC.SAFE_CASTdevuelveNULLcuando el valor no se puede convertir, en lugar de detener la consulta.SELECT 5 / 2; -- 2.5 (FLOAT64) SELECT DIV(5, 2); -- 2 SELECT SAFE_CAST('12,5' AS NUMERIC); -- NULL en vez de errorSQL ServerSnowflake
TRY_CASTdevuelveNULLsi la conversión falla. SQL Server hace división entera entre enteros, igual que PostgreSQL; Snowflake devuelve decimales.SELECT TRY_CAST('12,5' AS DECIMAL(10, 2)); -- NULL en vez de errorPostgreSQLSnowflake
La forma corta
valor::tiposolo existe en PostgreSQL y Snowflake.CAST(valor AS tipo)es la forma del estándar y funciona en todos los motores.
Estos fragmentos no se ejecutan en el curso: se muestran como referencia de cada motor.