Ir al contenido
wannacode

Aritmética en una consulta

En resumen: En SELECT puedes calcular con columnas (+, -, *, /) para cada fila y redondear con ROUND, pero en SQLite, PostgreSQL y SQL Server dividir dos enteros descarta la parte decimal.

Problema

¿Cuánto cuesta esta línea?

Contabilidad quiere saber, para cada línea de pedido, cuánto cuesta: la cantidad por el precio. La tabla order_items solo tiene los dos números:

SQLbase de datos: tienda

El pedido 3 tiene manzanas, 4 a 2,10 €, y detergente en polvo, 3 a 12,50 €. Calcular a mano 152 líneas no es trabajo para una persona. Y guardar el total en otra columna más significa mantenerlo correcto después de cada cambio.

La idea

Una columna calculada

Además de columnas, SELECT puede contener expresiones: cálculos con las columnas. La base los calcula para cada fila:

SQLbase de datos: tienda

Los operadores son +, -, *, / y % (el resto de una división). La columna calculada se llama como la propia expresión, así que le das un alias corto con AS. La tabla no cambia: el cálculo existe solo en el resultado.

También puedes ordenar por el alias. Las cinco líneas más caras de todos los pedidos:

SQLbase de datos: tienda

Una expresión funciona también sin tabla. Entonces SELECT la calcula una vez, como una calculadora. La multiplicación va antes que la suma, y los paréntesis cambian el orden:

SQLbase de datos: tienda

Pruébalo

El precio con IVA

Los precios de la base son sin IVA. Muestra el nombre, el precio y el precio con un 20 % de IVA en una columna llamada with_vat.

SQLbase de datos: tienda

Míralo

La puntuación como porcentaje

El sitio web quiere mostrar las puntuaciones de 1 a 5 como porcentajes: 5 es 100 %, 4 es 80 %. Ejecuta:

SQLbase de datos: tienda
1. La reseña con 4 salió como 0 %. ¿Por qué?

Esto es la división entera. Cuando los dos números son enteros, el resultado también lo es:

SQLbase de datos: tienda

En cuanto uno de los números es una fracción (2.0), o se convierte en una con CAST(… AS REAL), la división conserva la parte decimal. Para los porcentajes basta con multiplicar primero, por 100.0:

SQLbase de datos: tienda

Con price esta trampa no ocurre: el precio es un número con decimales (REAL). Ojo con las columnas que guardan enteros, como rating, quantity y stock.

Más precisamente, para curiosos

PostgreSQL y SQL Server dividen los enteros igual: 5 / 2 es 2. MySQL hace lo contrario: allí 5 / 2 es 2.5000, y la división entera tiene su propio operador, DIV. Dividir entre cero da NULL en SQLite y un error en PostgreSQL.

La idea

ROUND: al céntimo

Una promoción: 15 % de descuento en los lácteos. El precio nuevo es el 85 % del anterior:

SQLbase de datos: tienda

Nadie puede pagar 0,935 € por un yogur. ROUND(x, 2) redondea a dos dígitos después del punto, es decir, al céntimo. ROUND(x) redondea a un número entero.

Mira el queso blanco: 6.715 se volvió 6.71, no 6.72. Por qué, lo ves más abajo.

Más precisamente, para curiosos

Los números con decimales se guardan en la computadora en binario, y en binario el 0.1 no tiene una forma exacta, igual que 1/3 no la tiene en cifras decimales. Por eso:

SQLbase de datos: tienda

La pantalla muestra 0.3, pero la comparación dice «no» (0). printf con %!.20f muestra lo que de verdad está guardado. El queso blanco es la misma historia: 7.9 × 0.85 es 6.71499… en memoria, y ROUND lo redondea hacia abajo con honestidad.

Por eso los sistemas reales no guardan el dinero como REAL. Lo guardan en céntimos enteros (1,20 € es 120), o en un tipo para números decimales exactos: NUMERIC(10, 2) o DECIMAL(10, 2) en PostgreSQL, MySQL y SQL Server. SQLite no tiene un tipo así, de modo que allí el camino son los céntimos:

SQLbase de datos: tienda

En céntimos, 790 × 85 es exactamente 67 150, y al dividir entre 100 da 671.5 céntimos, que se redondean a 672, es decir, 6,72 €.

Pruébalo

La promoción

Muestra el nombre, el precio y el precio de oferta de cada producto. El precio de oferta es price * 0.85, redondeado al céntimo, en una columna llamada sale_price.

SQLbase de datos: tienda

Ejercicio

Dos tareas

1. La aseguradora pregunta cuánto vale la mercancía del almacén. Muestra los cinco productos con mayor valor en existencias (precio por existencias), el mayor primero. La tarjeta de regalo no es mercancía en un estante: conserva solo los productos que tienen categoría.

Nombre, stock y stock_value, los cinco mayores:

SQLbase de datos: tienda

2. La mercancía llega en cajas de 12. Para cada producto con categoría que haya en existencia, muestra cuántas cajas completas hay (boxes) y cuántas unidades quedan fuera de ellas (loose).

Nombre, stock, boxes y loose:

SQLbase de datos: tienda

Test

Ponte a prueba

1. ¿Qué devuelve SELECT 7 / 2;?
2. ¿Cambia SELECT price * 1.2 AS with_vat FROM products; los precios de la tabla?
3. ¿Cuál ordena las líneas de pedido por valor, la mayor primero?
4. ¿Qué da ROUND(2.345, 1)?

Creado por Ivo Gergov como parte de la campaña de Evo Tech por una educación accesible en programación ·