Beginner: asking questions · Functions, CASE and NULL · topic 12 of 62 · 30 min
Numbers and maths
Explanation
Why maths inside the database?
Reports need numbers that are not stored: a price with GST, a discount, a percentage, a daily rate from a monthly salary. Working them out in the query means every screen and report uses the same formula, and only the result travels to the app. In module 2 you met + − * / and ROUND; this topic goes deeper into the traps.
Integer division, again and properly
An integer is a whole number, like 7 or 95000. A real (or decimal) number has a fraction, like 3.5. When both sides of / are integers, SQLite, PostgreSQL and SQL Server give an integer answer and simply drop the fraction. MySQL and Oracle give a decimal answer.
SELECT name, salary, salary / 30 AS wrong_day, ROUND(salary / 30.0, 2) AS day_pay
FROM employees WHERE id IN (3, 9);
-- Anita Desai | 95000 | 3166 | 3166.67
-- Neha Joshi | 68000 | 2266 | 2266.67| Expression | SQLite / PostgreSQL / SQL Server | MySQL |
|---|---|---|
| 7 / 2 | 3 | 3.5000 |
| 7 / 2.0 | 3.5 | 3.5000 |
| 7 * 1.0 / 2 | 3.5 | 3.5000 |
| CAST(7 AS REAL) / 2 | 3.5 | 3.5 (7 / 2 is enough) |
| Whole-number division on purpose | 7 / 2 → 3 | 7 DIV 2 → 3 |
CAST: changing the type
CAST(value AS type) converts a value. CAST(7 AS REAL) gives 7.0, CAST('42' AS INTEGER) turns text into the number 42, and CAST(3.99 AS INTEGER) gives 3, because CAST cuts off the fraction instead of rounding. Use ROUND when you want rounding.
ROUND and ABS
ROUND(x, 2) keeps two decimal places; ROUND(x) keeps none. SQLite rounds halves away from zero, so ROUND(2.5) is 3 and ROUND(-2.5) is −3. ABS(x) gives the size of a number without its sign: ABS(−250) is 250, handy for the difference between two amounts when you do not care which is bigger.
SELECT 1.1 + 2.2; -- 3.3000000000000003
SELECT ROUND(1.1 + 2.2, 2); -- 3.3% : the remainder
a % b gives what is left over after dividing a by b. 17 % 5 is 2. Two common uses: id % 2 = 0 picks even ids (useful to split rows into two groups), and stock % 6 gives the loose items after packing boxes of six. PostgreSQL, MySQL and Oracle also have MOD(a, b).
SELECT name, stock, stock / 6 AS full_boxes, stock % 6 AS loose
FROM products WHERE id <= 3;
-- Basmati Rice 5kg | 40 | 6 | 4
-- Toor Dal 1kg | 75 | 12 | 3
-- Steel Tiffin Box | 12 | 2 | 0GST and discount maths
- GST amount: price * 0.18. Price with GST: price * 1.18.
- A discount of d percent: price * (1 − d / 100.0). A 15% discount is price * 0.85.
- Discount first, then GST: price * 0.9 * 1.18. Multiplication order does not change the answer, but say clearly in the report which came first.
- Percentage of a total: part * 100.0 / total, then ROUND.
SELECT name, price, ROUND(price * 0.18, 2) AS gst, ROUND(price * 1.18, 2) AS total
FROM products WHERE id IN (2, 5);
-- Toor Dal 1kg | 160 | 28.8 | 188.8
-- Cotton Kurta | 899 | 161.82 | 1060.82Common mistakes
- Integer division giving 0 or a cut-off answer. Put the 100.0 or 1.0 first: x * 100.0 / y.
- Expecting CAST(3.99 AS INTEGER) to give 4. CAST cuts; ROUND rounds.
- Rounding in the middle of a calculation and then adding: small differences pile up. Round the final value.
- Comparing reals for exact equality: 1.1 + 2.2 = 3.3 is false in SQLite. Compare rounded values.
- Dividing by a column that can be 0. Topic 5 shows NULLIF for that.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Numbers and maths · 1/7
Reports need numbers that are not stored: GST, discounts, percentages, daily pay. SQL works them out row by row.
Prefer a video by a teacher? Find free videos on “sql arithmetic integer division cast round modulo tutorial” on YouTube ↗
In real life: Working out an invoice on a billing app
A billing app used by small shops stores each item's price and the discount on the bill. At checkout the query applies the discount, adds 18% GST and rounds to two places, so the printed bill, the shop's report and the GST summary all use one formula. Shops that need exact paise usually store amounts as integers in paise and divide by 100 only for display.
SELECT name,
price,
ROUND(price * 0.9, 2) AS after_discount,
ROUND(price * 0.9 * 1.18, 2) AS to_pay
FROM products
WHERE category = 'Fashion';Practice (0/4 done)
Sale day: Fashion products get 10% off, then 18% GST is added. Return name, price, and price * 0.9 * 1.18 rounded to 2 decimal places, named final_price, for products in the Fashion category.
The exam was out of 120. Return name, marks, and the percentage (marks out of 120, times 100) rounded to 1 decimal place, named percent. Watch out for integer division.
Split the class into two groups by id. Return id and name of students with an even id.
The warehouse packs items in boxes of 6. From products, return name, stock, the number of full boxes named full_boxes, and the items left over named loose.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Working with datesFunctions, CASE and NULL · same module
- CASE expressionsFunctions, CASE and NULL · same module
- Numbers and mathsPython Programming · First steps in Python
- Operators, conversions and parsing inputC# and .NET · Getting started with C# and .NET
- Type conversion and castingC Programming (from zero to systems) · Operators and control flow
- Type conversion and reading inputJava Programming (Core to Spring Boot) · Getting started with Java
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
In SQLite, what does SELECT 45 / 120 * 100; return?
Answer: 0
45 / 120 is integer division and gives 0, and 0 * 100 is 0. Write 45 * 100.0 / 120 instead.
What does CAST(9.99 AS INTEGER) return?
Answer: 9
CAST cuts off the fraction; it does not round. Use ROUND(9.99) for 10.
Which expression gives the price after a 15% discount?
Answer: price * 0.85
Paying 85% of the price is the same as taking 15% off.
What is 23 % 5?
Answer: 3
23 = 4 × 5 + 3, so the remainder is 3.
A query that works in MySQL returns 3.5 for 7 / 2, but 3 after moving to PostgreSQL with integer columns. Why?
Answer: PostgreSQL integer / integer drops the fraction; MySQL's / always keeps it
Make one side a decimal (7 * 1.0 / 2, or CAST to numeric) so it works the same everywhere.
What does Math.Round(2.5) return in C#?Related
Answer: 2
By default C# uses banker's rounding: halfway values go to the nearest even number.
What type is the result of 3 + 2.0?Related
What type does Math.round(2.5) return?Related
Answer: long
Math.round(double) returns a long (Math.round(float) returns int).
What is static_cast<int>(9.99)?Related
Answer: 9
Converting a double to an int cuts off the fraction; it does not round.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 3 more topics in “Functions, CASE and NULL” before its exam: Working with dates, CASE expressions, NULL: the missing value.
- Module 3 exam: Functions, CASE and NULL · 15 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Aggregation: GROUP BY and HAVING. 62 topics left in the course before the final exam.