23. Math Functions & CASE Logic -- Calculations and Conditionals
Level: Guided beginner
- ROUND, CEILING, FLOOR -- numeric rounding
- ABS -- absolute value
- SQRT, POWER -- roots and exponents
- CASE expression -- conditional logic
- Simple CASE vs searched CASE
- CASE for transforming data
- Multiple CASE conditions
- Common math/CASE mistakes
- Best practices
Math functions calculate. CASE expressions conditionally transform. Together they power business logic. This article teaches calculations and conditionals.
Why Math & CASE Matter for Backend Developers
APIs need conditional business logic:
Frontend asks: "Show student grade (A/B/C/F) based on marks,
with fees discounted if class avg > 80"
v
Backend needs:
- Calculate percentage (math)
- Assign grade based on range (CASE)
- Conditional discount (nested CASE)
v
Math functions and CASE expressions solve in SQL
v
Return transformed data
CASE expressions replace complex if-else chains.
Math Functions Reference
ROUND(number, decimals) -> Round to decimal places
CEILING(number) -> Smallest integer >= value
FLOOR(number) -> Largest integer <= value
ABS(number) -> Absolute value (remove sign)
SQRT(number) -> Square root
POWER(number, exponent) -> Power (number^exponent)
Example 1: Round Exam Marks
Round to nearest integer:
SELECT
s.Name AS Student,
r.MarksObtained AS RawMarks,
ROUND(r.MarksObtained, 0) AS RoundedMarks,
ROUND(r.MarksObtained, 1) AS OneDec,
ROUND(r.MarksObtained, 2) AS TwoDec
FROM Student s
INNER JOIN ExamResult r ON s.StudentId = r.StudentId;
Result (rounding):
Student | RawMarks | RoundedMarks | OneDec | TwoDec
Ravi Kumar | 92.456 | 92 | 92.5 | 92.46
Priya Sharma| 85.624 | 86 | 85.6 | 85.62
ROUND(value, 0): Integer. ROUND(value, 1): 1 decimal place.
Example 2: Percentage Calculation
Calculate percentage with proper rounding:
SELECT
s.Name AS Student,
r.MarksObtained,
e.MaxMarks,
ROUND(r.MarksObtained * 100.0 / e.MaxMarks, 2) AS Percentage
FROM Student s
INNER JOIN ExamResult r ON s.StudentId = r.StudentId
INNER JOIN Exam e ON r.ExamId = e.ExamId
ORDER BY Percentage DESC;
Result (percentages):
Student | MarksObtained | MaxMarks | Percentage
Ravi Kumar | 92 | 100 | 92.00
Priya Sharma| 85 | 100 | 85.00
Arjun Reddy | 78 | 100 | 78.00
Multiply by 100.0 (FLOAT), divide by MaxMarks, ROUND to 2 decimals.
Example 3: CASE Expression (Simple)
Assign grade based on marks:
SELECT
s.Name AS Student,
r.MarksObtained,
CASE r.MarksObtained
WHEN 90 THEN 'A+'
WHEN 80 THEN 'A'
WHEN 70 THEN 'B'
WHEN 60 THEN 'C'
ELSE 'F'
END AS Grade
FROM Student s
INNER JOIN ExamResult r ON s.StudentId = r.StudentId;
Result (grades):
Student | MarksObtained | Grade
Ravi Kumar | 92 | A+
Priya Sharma| 85 | A
Arjun Reddy | 78 | B
Simple CASE: Match exact value. Not useful for ranges.
Example 4: CASE Expression (Searched -- ranges)
Assign grade by range:
SELECT
s.Name AS Student,
r.MarksObtained,
CASE
WHEN r.MarksObtained >= 90 THEN 'A+'
WHEN r.MarksObtained >= 80 THEN 'A'
WHEN r.MarksObtained >= 70 THEN 'B'
WHEN r.MarksObtained >= 60 THEN 'C'
ELSE 'F'
END AS Grade
FROM Student s
INNER JOIN ExamResult r ON s.StudentId = r.StudentId
ORDER BY r.MarksObtained DESC;
Result (grades by range):
Student | MarksObtained | Grade
Ravi Kumar | 92 | A+
Priya Sharma| 85 | A
Arjun Reddy | 78 | B
Kiran Rao | 65 | C
Searched CASE (WHEN condition): For ranges, multiple conditions.
Example 5: Nested CASE
Multiple conditions (grade + bonus):
SELECT
s.Name AS Student,
r.MarksObtained,
CASE
WHEN r.MarksObtained >= 90 THEN 'A+'
WHEN r.MarksObtained >= 80 THEN 'A'
ELSE 'B'
END AS Grade,
CASE
WHEN r.MarksObtained >= 90 THEN 10
WHEN r.MarksObtained >= 80 THEN 5
ELSE 0
END AS BonusPoints
FROM Student s
INNER JOIN ExamResult r ON s.StudentId = r.StudentId;
Result (grade + bonus):
Student | MarksObtained | Grade | BonusPoints
Ravi Kumar | 92 | A+ | 10
Priya Sharma| 85 | A | 5
Arjun Reddy | 78 | B | 0
Multiple CASE expressions per row. Each independent.
Example 6: CASE in WHERE Clause
Filter by conditional logic:
SELECT
s.Name AS Student,
r.MarksObtained,
CASE
WHEN r.MarksObtained >= 75 THEN 'Pass'
ELSE 'Fail'
END AS Result
FROM Student s
INNER JOIN ExamResult r ON s.StudentId = r.StudentId
WHERE CASE
WHEN r.MarksObtained >= 75 THEN 'Pass'
ELSE 'Fail'
END = 'Pass'
ORDER BY r.MarksObtained DESC;
Result (pass students only):
Student | MarksObtained | Result
Ravi Kumar | 92 | Pass
Priya Sharma| 85 | Pass
CASE in WHERE: Filter by conditional result.
Example 7: Fee Discount Logic
Apply discount based on class average:
SELECT
s.Name AS Student,
f.TotalFees,
CASE
WHEN AVG(r.MarksObtained) OVER (PARTITION BY s.ClassName) > 80
THEN ROUND(f.TotalFees * 0.9, 0) -- 10% discount
WHEN AVG(r.MarksObtained) OVER (PARTITION BY s.ClassName) > 70
THEN ROUND(f.TotalFees * 0.95, 0) -- 5% discount
ELSE f.TotalFees -- No discount
END AS DiscountedFees
FROM Student s
LEFT JOIN FeeAccount f ON s.StudentId = f.StudentId
LEFT JOIN ExamResult r ON s.StudentId = r.StudentId
GROUP BY s.StudentId, s.Name, f.TotalFees, s.ClassName;
Result (discounts):
Student | TotalFees | DiscountedFees
Ravi Kumar | 50000 | 45000 (10% discount, class avg > 80)
Priya Sharma| 50000 | 47500 (5% discount, class avg > 70)
CASE with window function: Conditional based on aggregate.
Example 8: Absolute Value (Difference)
Get absolute difference from average:
SELECT
s.Name AS Student,
r.MarksObtained,
AVG(r.MarksObtained) OVER () AS OverallAverage,
ABS(r.MarksObtained - AVG(r.MarksObtained) OVER ()) AS DifferenceFromAverage
FROM Student s
INNER JOIN ExamResult r ON s.StudentId = r.StudentId;
Result (deviation):
Student | MarksObtained | OverallAverage | DifferenceFromAverage
Ravi Kumar | 92 | 81.5 | 10.5
Priya Sharma| 85 | 81.5 | 3.5
Arjun Reddy | 70 | 81.5 | 11.5
ABS: Always positive distance from average.
Common Math & CASE Mistakes
Mistake 1: CASE without ELSE
Wrong:
SELECT
MarksObtained,
CASE
WHEN MarksObtained >= 90 THEN 'A+'
WHEN MarksObtained >= 80 THEN 'A'
END AS Grade
FROM ExamResult;
-- Marks < 80: NULL grade
Result: NULL for unhandled cases.
Fix: Add ELSE:
CASE
WHEN MarksObtained >= 90 THEN 'A+'
WHEN MarksObtained >= 80 THEN 'A'
ELSE 'F'
END AS Grade
Mistake 2: Integer division losing decimals
Wrong:
SELECT
MarksObtained * 100 / MaxMarks AS Percentage
-- 85 * 100 / 100 = 8500 / 100 = 85 (integer)
-- 92 * 100 / 100 = 9200 / 100 = 92 (integer)
-- No decimals
Result: Integer percentages (no decimal precision).
Fix: Use FLOAT:
SELECT
ROUND(MarksObtained * 100.0 / MaxMarks, 2) AS Percentage
-- 100.0 forces float, preserves decimals
Mistake 3: CASE condition order matters
Wrong:
CASE
WHEN MarksObtained >= 60 THEN 'Pass'
WHEN MarksObtained >= 90 THEN 'A+' -- Never reached (already matched >= 60)
END
Result: 95 marks shows "Pass", not "A+" (first match wins).
Fix: Order conditions from specific to general:
CASE
WHEN MarksObtained >= 90 THEN 'A+'
WHEN MarksObtained >= 80 THEN 'A'
WHEN MarksObtained >= 60 THEN 'Pass'
ELSE 'Fail'
END
Mistake 4: Using CASE with NULL
Wrong:
CASE
WHEN MarksObtained = NULL THEN 'Absent' -- Always false (NULL != NULL)
ELSE 'Present'
END
Result: All present (absent never matched).
Fix: Use IS NULL:
CASE
WHEN MarksObtained IS NULL THEN 'Absent'
ELSE 'Present'
END
Mistake 5: Complex CASE logic in WHERE
Wrong:
SELECT * FROM ExamResult
WHERE CASE
WHEN MarksObtained >= 80 THEN 'Pass'
ELSE 'Fail'
END = 'Pass';
-- Works but slow: repeats CASE for every row
Result: Performance hit.
Fix: Use direct condition:
WHERE MarksObtained >= 80;
-- Simpler, faster
Reserve CASE for complex transforms, not simple filters.
Best Practices for Math & CASE
- Use 100.0 for percentage -- Ensures float division
- CASE with ELSE -- Handle all cases explicitly
- Order CASE from specific to general -- First match wins
- IS NULL in CASE, not = NULL -- NULL never equals anything
- Avoid CASE in WHERE if possible -- Use direct condition
- Test edge cases -- NULL, zero, negative numbers
- Round at display -- Not intermediate calculations
ROUND: Nearest value.
ROUND(92.456, 0) -- 92
ROUND(92.556, 0) -- 93
CEILING: Smallest integer >= value.
CEILING(92.1) -- 93
CEILING(92.0) -- 92
FLOOR: Largest integer <= value.
FLOOR(92.9) -- 92
FLOOR(92.0) -- 92
Use ROUND for normal rounding. CEILING/FLOOR for always up/down.
Simple CASE (exact match):
CASE MarksObtained
WHEN 90 THEN 'A+'
WHEN 80 THEN 'A'
ELSE 'F'
END
Searched CASE (conditions):
CASE
WHEN MarksObtained >= 90 THEN 'A+'
WHEN MarksObtained >= 80 THEN 'A'
ELSE 'F'
END
Simple: Exact values. Searched: Ranges and complex conditions. Searched more common.
Always use FLOAT in division:
SELECT
MarksObtained,
MaxMarks,
ROUND(MarksObtained * 100.0 / MaxMarks, 2) AS Percentage
FROM ExamResult;
Multiply by 100.0 (not 100) -- forces float. Divide after. ROUND for decimals.
Why: 85 * 100 / 100 (integer) = 85. 85 * 100.0 / 100 (float) = 85.00.
Yes, first match wins:
CASE
WHEN MarksObtained >= 60 THEN 'Pass'
WHEN MarksObtained >= 90 THEN 'A+' -- Never reached for 95
END
-- 95 matches first condition (>= 60), returns 'Pass'
Correct order (specific to general):
CASE
WHEN MarksObtained >= 90 THEN 'A+'
WHEN MarksObtained >= 60 THEN 'Pass'
ELSE 'Fail'
END
Order from most specific to most general.
Yes, but avoid if possible:
SELECT * FROM Student s
INNER JOIN ExamResult r ON s.StudentId = r.StudentId
WHERE CASE WHEN r.MarksObtained >= 80 THEN 1 ELSE 0 END = 1;
-- Works but slow
Better:
WHERE r.MarksObtained >= 80;
CASE in WHERE: Reserved for complex conditional logic only. Direct condition faster.
Wrong (never matches NULL):
CASE WHEN Marks = NULL THEN 'Absent' -- Never true
Correct (use IS NULL):
CASE
WHEN Marks IS NULL THEN 'Absent'
WHEN Marks >= 60 THEN 'Pass'
ELSE 'Fail'
END
NULL never equals anything (NULL = NULL is false). Use IS NULL / IS NOT NULL.
Use ChatGPT, Claude, or Copilot to go deeper on Math functions and CASE expressions in SQL Server. Try these prompts:
"Show how to round exam percentage to 2 decimals""Explain CASE expression: assign grade (A/B/C/F) by marks range""What's the difference between ROUND, CEILING, FLOOR?""How do I safely calculate percentage (avoid integer division)?""Quiz me: ask 5 questions about CASE, ROUND, grade logic"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.