En SQL Server, AVG sobre una columna INT devuelve un INT: el promedio de 5, 4, 4 y 4 sale 4 en lugar de 4.25, porque se descartan los decimales. Para obtenerlos, convierte la columna antes de promediar: AVG(CAST(estrellas AS DECIMAL(10, 2))) o AVG(estrellas * 1.0). PostgreSQL, MySQL y SQLite sí devuelven decimales con AVG, pero los tres (salvo MySQL) truncan cuando calculas el promedio a mano con SUM(x) / COUNT(*).
Qué hace cada motor
| Motor | AVG(columna_int) | SUM(int) / COUNT(*) | 7 / 2 |
|---|---|---|---|
| SQL Server | int, trunca: 4 | División entera: 4 | 3 |
| PostgreSQL | numeric: 4.2500000000000000 | División entera: 4 | 3 |
| MySQL | DECIMAL: 4.2500 | Decimal: 4.2500 | 3.5000 |
| SQLite | Punto flotante: 4.25 | División entera: 4 | 3 |
| Oracle | NUMBER: 4.25 | 4.25 | 3.5 |
La regla general: si los dos operandos de / son enteros, SQL Server, PostgreSQL y SQLite hacen división entera. MySQL y Oracle no; MySQL tiene un operador aparte, DIV, para la división entera.
Paso a paso
- Revisa el tipo de la columna (
INT,SMALLINT,BIGINT,TINYINTson enteros). - Si usas SQL Server, convierte siempre antes de
AVG:AVG(CAST(col AS DECIMAL(10, 2))). - Si divides a mano, haz que al menos un operando sea decimal:
SUM(col) * 1.0 / COUNT(*). - Redondea el resultado con
ROUND(..., 2)o conviértelo conCAST(... AS DECIMAL(10, 2))para mostrarlo.
Tabla de ejemplo: reseñas de 1 a 5 estrellas.
CREATE TABLE resenas (
producto VARCHAR(20),
estrellas INT
);
INSERT INTO resenas VALUES
('Audífonos', 5), ('Audífonos', 4), ('Audífonos', 4), ('Audífonos', 4),
('Cargador', 5), ('Cargador', 2), ('Cargador', 4);
Ejemplos resueltos
Ejemplo 1: la misma consulta en SQLite y en SQL Server
SELECT producto,
AVG(estrellas) AS promedio,
SUM(estrellas) / COUNT(*) AS division_entera,
SUM(estrellas) * 1.0 / COUNT(*) AS por_uno
FROM resenas
GROUP BY producto;
Resultado en SQLite:
| producto | promedio | division_entera | por_uno |
|---|---|---|---|
| Audífonos | 4.25 | 4 | 4.25 |
| Cargador | 3.6666666666666665 | 3 | 3.6666666666666665 |
En SQL Server, la columna promedio también mostraría 4 y 3, igual que division_entera. Los Audífonos suman 17 en 4 reseñas (4.25) y el Cargador 11 en 3 (3.67). Truncar a 3 hace parecer que el Cargador está a más de medio punto de distancia de lo que realmente está. Multiplicar por 1.0 convierte la suma en decimal antes de dividir y funciona en todos los motores.
Ejemplo 2: versión portable con dos decimales
SELECT producto,
ROUND(AVG(estrellas * 1.0), 2) AS promedio
FROM resenas
GROUP BY producto;
| producto | promedio |
|---|---|
| Audífonos | 4.25 |
| Cargador | 3.67 |
estrellas * 1.0 es decimal en todos los motores, así que AVG ya no trunca en SQL Server y ROUND funciona también en PostgreSQL, donde ROUND(valor, 2) exige numeric. Si prefieres que el tipo quede explícito, usa AVG(CAST(estrellas AS DECIMAL(10, 2))). En SQL Server el resultado se mostrará con seis decimales (4.250000) hasta que lo conviertas: CAST(AVG(CAST(estrellas AS DECIMAL(10, 2))) AS DECIMAL(10, 2)).
Ejemplo 3: el porcentaje que siempre sale 0
Para el porcentaje de reseñas de 5 estrellas, una consulta muy común es:
SELECT SUM(CASE WHEN estrellas = 5 THEN 1 ELSE 0 END) / COUNT(*) * 100 AS pct
FROM resenas;
En SQL Server, PostgreSQL y SQLite devuelve 0: 2 / 7 es 0 en división entera, y 0 × 100 sigue siendo 0. La corrección:
SELECT ROUND(100.0 * SUM(CASE WHEN estrellas = 5 THEN 1 ELSE 0 END) / COUNT(*), 2) AS pct
FROM resenas;
Con 100.0 al principio, toda la expresión es decimal y el resultado es 28.57. Otra forma equivalente es AVG(CASE WHEN estrellas = 5 THEN 100.0 ELSE 0 END), porque el promedio de una columna de unos y ceros es la proporción de unos.
Errores comunes
- Convertir después de promediar.
CAST(AVG(estrellas) AS DECIMAL(10, 2))en SQL Server da 4.00: el promedio ya se truncó dentro delAVG. La conversión va adentro. - Multiplicar por 1.0 al final.
SUM(x) / COUNT(*) * 1.0divide primero (entero) y multiplica después. El1.0debe ir antes de la división. - Usar
FLOATpara dinero. Evita la división entera, pero introduce errores binarios. Para importes,DECIMAL. - Creer que
ROUNDagrega decimales.ROUND(4, 2)sigue siendo 4. Si el valor ya llegó entero, no hay decimales que recuperar. - Tipos
TINYINTySMALLINT. En SQL Server suAVGtambién esinty trunca igual.
Los problemas de redondeo del lado de la aplicación están en redondear el promedio en Python.
Fuentes
- Microsoft Learn, AVG (Transact-SQL). Tabla de tipos de retorno (int devuelve int). Consultado el 11 de noviembre de 2026.
- PostgreSQL, funciones de agregado. avg de smallint, integer y bigint devuelve numeric. Consultado el 11 de noviembre de 2026.
- MySQL 8.0 Reference Manual, funciones de agregado. SUM y AVG devuelven DECIMAL para argumentos exactos. Consultado el 11 de noviembre de 2026.
- SQLite, funciones de agregado. avg siempre devuelve punto flotante. Consultado el 11 de noviembre de 2026.