Module 2 › Conditional Logic & Casting

Conditional Logic & Casting: CASE WHEN, range banding & explicit CAST

Module 2, Session 11. Simple and Searched CASE WHEN branching, custom sort priorities, single-query conditional pivots, ANSI CAST, and PostgreSQL :: shorthand.

Jo class mein bola, yahan nukte mein likha hai.
What I said in class, written here as key points.

← All NukteSELECT * FROM TheShiraverse
MODULE 2 · SESSION 11

Conditional Logic & Casting:
CASE WHEN & CAST

Dynamic IF-THEN branching at row level, custom ordering priorities, single-query pivots, and explicit type conversions in PostgreSQL 18 on RetailMart.

23
Scenes
1
Practice Arena
4
Practice Drills
5
Interview Questions

Today’s Agenda — Conditional Logic & Casting

Four pillars: branching expressions, custom sorting, single-pass pivots, and explicit type conversions

Pillar 01
🧭 Searched & Simple CASE
01 Syntax mechanics: CASE WHEN ... THEN ... ELSE
02 Simple CASE: equality matching on single expressions
03 Order of evaluation: top-to-bottom short-circuit
Pillar 02
💹 Data Categorization & Binning
04 Numeric banding: customer spending & salary tiers
05 Priority sorting: custom ordering in ORDER BY
06 Multi-condition logic: compound boolean branches
Pillar 03
📊 Conditional Aggregation
07 Single-pass pivot: COUNT(CASE WHEN ... END)
08 Revenue sum: SUM(CASE WHEN ... ELSE 0 END)
09 Zero table joins: compute multi-state KPIs at once
Pillar 04
🔄 Type Casting & Conversions
10 Explicit conversions: CAST(expr AS type)
11 PostgreSQL shorthand: expression::type
12 Safe casting: text to integers, dates & numerics
💡
Why this matters: Real business data rarely comes neatly labeled. RetailMart's 1,50,000 orders must be categorized into VIP segments, tiered into shipping priorities, and aggregated into financial dashboards in a single scan without procedural code.

Where We Left Off: Temporal Arithmetic to Conditional Logic

From deterministic date arithmetic to dynamic declarative branch evaluation

📅 SESSION 10 • COMPLETED

Dates, Times & Intervals

-- Session 10: temporal precision & interval arithmetic
SELECT order_id, order_date,
order_date + INTERVAL '14 days' AS deadline
FROM sales.orders
ORDER BY order_id LIMIT 3;
-- 2024-05-02 + 14 days → 2024-05-16 00:00:00
Session 10 mastered calendar math (INTERVAL, AGE, EXTRACT, DATE_TRUNC, TO_CHAR). Every date calculation followed deterministic formulas. But business questions often require branch evaluation based on values.
✓ Temporal types locked; branching logic awaits
🧭 SESSION 11 • THE MISSION

Conditional Logic & Casting

-- “Classify order spending into tiers”
SELECT order_id, net_total,
CASE WHEN net_total >= 10000 THEN 'VIP'
     WHEN net_total >= 5000 THEN 'High'
     ELSE 'Regular' END AS tier
FROM sales.orders LIMIT 3;
CASE WHEN brings IF-THEN-ELSE expressiveness directly into SQL expressions. Combined with explicit CAST, we transform row values, define custom sort orders, and build multi-KPI pivots in a single query.
🧭 Today: CASE WHEN, CAST, and :: syntax
💡
The Core Rule: SQL is declarative, not procedural. CASE WHEN is not a statement that redirects control flow; it is an inline scalar expression that returns exactly one evaluated result for each row processed.
🧭
The Loyalty Tier Waterfall Disaster OUT-OF-ORDER THRESHOLDS • WATERFALL SHORT-CIRCUIT
ECOMMERCE • LOYALTY CAMPAIGN EXAMPLE STORY • NAMES & NUMBERS MADE UP ⚠ 2,400 VIP CARTS MISCLASSIFIED
STEP 01 • THE INCIDENT
crm-ops-bot 10:15 AM
“VIP Tier campaign launched! But corporate clients placing ₹50,000+ orders are receiving 'Silver' 2% vouchers instead of 'Platinum' 15% VIP perks! Support hotline is jammed!”
Analyst wrote WHEN net_total >= 1000 THEN 'Silver' before WHEN net_total >= 10000 THEN 'Platinum'.
STEP 02 • ROOT CAUSES
⚠ Inverted Waterfall Logic
Lowest Threshold First
The report checked the lowest threshold first. Because ₹25,000 is greater than ₹1,000, the first WHEN branch evaluated TRUE immediately.
⚡ Top-to-Bottom Short Circuit
Subsequent WHENs Ignored
SQL stops evaluating branches on the first match. The 'Platinum' check (>= 10000) was never reached for any order above ₹1,000.
💸 ₹14.2 Lakh in VIP Perks
Customer Complaints
Over 2,400 high-value shoppers received 2% basic vouchers instead of 15% VIP perks, triggering complaints before engineering deployed the fix.
STEP 03 • THE FIX
DESCENDING ORDER
🐙 Safe Waterfall Order
SELECT
  order_id,
  net_total,
  CASE
    WHEN net_total >= 10000 THEN 'Platinum'
    WHEN net_total >= 5000  THEN 'Gold'
    WHEN net_total >= 1000  THEN 'Silver'
    ELSE 'Standard'
  END AS tier
FROM sales.orders
ORDER BY net_total DESC, order_id
LIMIT 10;
-- Descending order prevents early match
✓ Evaluates 10000 First Highest to Lowest
STEP 04 • CORE PRINCIPLE
The Moral: CASE WHEN evaluates branches sequentially and stops at the very first TRUE condition. When checking ranges, always arrange thresholds from most restrictive to least restrictive (descending).

Mapping Business Logic to PostgreSQL Functions

Every crisis in the story translates directly into an essential conditional SQL rule.

🔣 Specificity Ordering
Problem: High performers misclassified due to premature broad condition match.
PostgreSQL Tool: CASE WHEN spend >= 100000 ... WHEN spend >= 50000.
Ensures narrow high-tier criteria evaluate before generic thresholds.
💣 The Silent NULL Drop
Problem: Omitting ELSE produces silent NULLs for unhandled row categories.
PostgreSQL Tool: ELSE 'Standard Member' END.
Guarantees every row in the dataset evaluates to a defined, report-ready value.
🛡 Type Uniformity
Problem: Returning numbers in one branch and text in another crashes execution.
PostgreSQL Tool: CAST(val AS TEXT) & uniform branch types.
All branches in a CASE expression must resolve to the same compatible data type.

Visual Studio: The Evaluation Waterfall

Click spend tiers to watch PostgreSQL evaluate conditions sequentially and short-circuit.

TEST SPEND SCENARIO:
Evaluating customer spend... Click a scenario button above to trace execution flow.
1. WHEN spend >= 100000 THEN 'Platinum VIP'
2. WHEN spend >= 50000 THEN 'Gold Member'
3. ELSE 'Standard Member'
Assigned Tier: Standby

CASE WHEN: The Conditional Expression Engine

PostgreSQL's native IF-THEN branching evaluated row by row during SELECT execution.

Pillar 01
Simple CASE
Compares an expression against discrete equality values: CASE tier WHEN 'Platinum' THEN .... Cleanest for status codes and category tags.
Pillar 02
Searched CASE
Evaluates independent boolean conditions: CASE WHEN salary >= 100000 THEN .... Essential for range comparisons (>, <) and compound logic.
Pillar 03
Short-Circuit Execution
Conditions evaluate sequentially top-to-bottom. The engine stops immediately at the first TRUE branch without evaluating subsequent clauses.
Simple CASE: Customer Tier Presentation Mapping
▶ Run Query
PostgreSQL 18
QUERYMap All 4 RetailMart Tiers with Simple CASE
SELECT customer_id,
  INITCAP(first_name) || ' ' || INITCAP(last_name) AS name,
  tier,
  CASE tier
    WHEN 'Platinum' THEN 'VIP Platinum Member'
    WHEN 'Gold'     THEN 'Premium Member'
    WHEN 'Silver'   THEN 'Regular Member'
    WHEN 'Bronze'   THEN 'Basic Member'
    ELSE 'Standard Member'
  END AS tier_label
FROM customers.customers
ORDER BY customer_id
LIMIT 10;

Visual Studio: Syntax Selection Matrix

Click to inspect capability differences between Simple and Searched CASE.

INSPECT CAPABILITY:
Simple CASE: Strict single-column equality tests. Fast, readable, but cannot do range comparisons or IS NULL checks.
💡 ARCHITECTURAL RULE When in doubt, always use Searched CASE. It supports range comparisons, IS NULL checks, and multi-column boolean criteria.

Beyond SELECT: CASE in WHERE & ORDER BY

Custom priority ranking and dynamic operational filtering without procedural code.

Technique 01
Custom Sort Priority
Assign custom integer weights to rank business statuses (e.g., Cancelled and Failed orders first for audit) instead of alphabetical order.
Technique 02
Dynamic WHERE Filters
Use CASE expressions inside WHERE to switch filter criteria based on transaction thresholds, avoiding fragmented UNION queries.
Technique 03
Multi-Key Tie Breaking
Pair the custom priority weight with secondary numeric columns: ORDER BY (CASE ...) ASC, net_total DESC for deterministic output.
Custom Priority Ordering on Real RetailMart Order Statuses
▶ Run Query
PostgreSQL 18
QUERYPrioritize Exception Statuses Over Normal Deliveries
SELECT order_id, cust_id, order_status, net_total
FROM sales.orders
ORDER BY
  CASE order_status
    WHEN 'Cancelled'  THEN 1
    WHEN 'Failed'     THEN 2
    WHEN 'Returned'   THEN 3
    WHEN 'Processing' THEN 4
    ELSE 5
  END ASC,
  net_total DESC
LIMIT 10;

Visual Studio: The Single-Query Pivot

Click to inspect how conditional aggregation pivots categorical rows into KPI columns.

INSPECT DATAFLOW:
Row Stream: 1,50,000 orders stream through the aggregator.
When status = Delivered, CASE returns 1; otherwise NULL. COUNT(1) increments only for Delivered orders!
⚡ PERFORMANCE DOMINANCE Conditional aggregation replaces 4 separate subqueries with a single table scan — the core foundation of production analytics dashboards.

The Single-Query Pivot: Conditional Aggregation

Computing multiple category KPIs in a single table scan using CASE inside aggregate functions.

Pattern 01
COUNT(CASE ... END)
Omit the ELSE branch! If unmatched, CASE returns NULL. Because COUNT(col) ignores NULLs, it counts only matching events cleanly.
Pattern 02
SUM(CASE ... ELSE 0 END)
Provide an explicit ELSE 0 for mathematical sums. Unmatched rows contribute ₹0 to the accumulator without NULL propagation.
Pattern 03
Curriculum Continuity
A preview: COUNT and SUM get their own class in Session 13, and numbers per store need GROUP BY in Session 14. Today: one row for the whole table.
Conditional Aggregation Pivot on Real RetailMart Orders
▶ Run Query
PostgreSQL 18
QUERYSingle Pass Dashboard KPIs in One Row
SELECT
  COUNT(*) AS total_orders,
  COUNT(CASE WHEN order_status = 'Delivered'
             THEN 1 END) AS delivered_orders,
  COUNT(CASE WHEN order_status = 'Cancelled'
             THEN 1 END) AS cancelled_orders,
  ROUND(SUM(CASE WHEN order_status = 'Delivered'
                 THEN net_total ELSE 0 END), 2) AS delivered_revenue
FROM sales.orders;

Pro Tips & Common CASE Pitfalls

Avoid the 4 silent logic bugs that corrupt production reporting queries.

⚠ Mistake 1: The Broad-Before-Narrow Trap
Wrong: WHEN salary > 20000 THEN 'Mid' WHEN salary > 80000 THEN 'Exec'
Why: An executive earning ₹1,20,000 matches > 20,000 first and gets labeled 'Mid'!
Fixed: Always check strictest limits first in descending order.
⚠ Mistake 2: Forgetting ELSE — Silent NULLs
Wrong: Omitting ELSE when classifying business categories.
Why: Any row not matching a WHEN branch evaluates to NULL, corrupting reports.
Fixed: Always supply an explicit safety net: ELSE 'Other'.
✔ Pro Tip 1: COUNT vs SUM in Aggregation
Never put ELSE 0 inside COUNT(CASE ...)! 0 is not NULL, so COUNT() counts every row: 1,50,000 instead of 7,587 cancelled orders. Use COUNT(CASE WHEN ... THEN 1 END) or SUM(CASE WHEN ... THEN 1 ELSE 0 END).
✔ Pro Tip 2: Simple CASE NULL Hazard
CASE col WHEN NULL THEN 'X' NEVER matches! In Simple CASE, this tests col = NULL, which evaluates to UNKNOWN. For NULL checks, always use Searched CASE: WHEN col IS NULL THEN 'X'.
65%
🧠Practice Time

Visual Studio: Type Conversion Mechanics

Click to inspect explicit casting and numeric rounding behavior in PostgreSQL.

TEST CONVERSION:
price::INT → 1499.95 becomes 1500 (rounds to nearest integer).
💡 CASTING RULE All branches of a CASE expression must return the same data type. Use explicit CAST or :: to convert incompatible values before returning them.

Type Conversion: Explicit Casting Mechanics

Mastering ANSI CAST and PostgreSQL shorthand to prevent silent data corruption.

Pillar 01
ANSI SQL Standard
CAST(expression AS target_type)
Universal across Oracle, MySQL, SQL Server, BigQuery, and Snowflake. The gold standard for portable enterprise code.
Pillar 02
PostgreSQL Shorthand
expression::target_type
Clean, idiomatic PostgreSQL syntax. Highly favored in analytics queries for quick inline coercions (e.g. id::TEXT, ts::DATE).
Pillar 03
Formatting vs Casting
Casting changes a value's data type. For formatted strings with commas and currency symbols, use TO_CHAR(val, 'FM...').
Type Casting & Display Formatting on RetailMart Products
▶ Run Query
PostgreSQL 18
QUERYExplicit Casting vs TO_CHAR Presentation
SELECT product_id,
  CAST(product_id AS TEXT) AS id_standard_cast,
  product_id::TEXT AS id_postgres_shorthand,
  price,
  price::INT AS rounded_integer_price,
  TO_CHAR(price, 'FM₹ 99,99,999.00') AS display_rupee_string
FROM products.products
ORDER BY product_id
LIMIT 10;

Interview Studio: Master CASE & Casting Questions

Five core conditional logic questions interviewers ask, with production-grade answers.

Q1 Simple vs Searched CASE
Q2 Branch Type Consistency
Q3 CASE vs Application Logic
Q4 CAST vs :: vs TO_CHAR
Q5 CASE vs DECODE
Q1 · Simple vs Searched CASE
What is the technical difference between Simple CASE and Searched CASE?
Answer to give:
Simple CASE compares a single test expression against discrete literal values using equality: CASE tier WHEN 'Gold' THEN 1 END. It cannot evaluate inequality (>, <) or check IS NULL because tier = NULL resolves to UNKNOWN. Searched CASE evaluates independent boolean predicates per branch: CASE WHEN marks >= 90 THEN 'A' WHEN marks IS NULL THEN 'Absent' END. Searched CASE is vastly more expressive.

Self-Check Studio: 6 Conditional Retention Cards

Click any flashcard to flip and test your understanding of PostgreSQL branching rules.

CLICK TO FLIP • SELF-CHECK
What does a CASE expression evaluate to if no WHEN matches and ELSE is omitted?
ANSWER: NULL. In SQL, if no branch condition is met and no explicit ELSE clause is provided, the CASE expression defaults to NULL.
CLICK TO FLIP • SELF-CHECK
What does price::INT do to a decimal price of 1499.95 in PostgreSQL?
ANSWER: Rounds to 1500. In PostgreSQL, casting numeric to integer rounds to the nearest whole integer. To truncate decimals without rounding, use TRUNC(price)::INT.
CLICK TO FLIP • SELF-CHECK
Why does CASE tier WHEN NULL THEN 'X' END fail to match NULL tiers?
ANSWER: Simple CASE performs equality comparison (tier = NULL), which evaluates to UNKNOWN in 3-valued logic. Use Searched CASE: WHEN tier IS NULL.
CLICK TO FLIP • SELF-CHECK
What happens if conditions in a Searched CASE are ordered from broad to narrow?
ANSWER: The broader condition catches rows first, short-circuiting before narrower rules evaluate. Always order conditions from strictest/narrowest to broadest.
CLICK TO FLIP • SELF-CHECK
Why should you omit ELSE in COUNT(CASE WHEN status = 'Late' THEN 1 END)?
ANSWER: Omitting ELSE returns NULL for non-matching rows. Because COUNT(col) ignores NULLs, it counts only matching events. ELSE 0 would count every row!
CLICK TO FLIP • SELF-CHECK
What is the result of dividing two integers 5 / 2 in PostgreSQL?
ANSWER: 2 (integer division truncates fractions). To get 2.50, cast at least one operand: 5.0 / 2 or 5::NUMERIC / 2.

Key Takeaways: The 6 Conditional Laws

Universal principles for writing robust conditional expressions and data transformations.

01
Narrow Before Broad
CASE short-circuits at the first TRUE match. Always evaluate narrow, strict conditions before broader thresholds to prevent misclassification.
02
Mandatory ELSE Safety Net
Omitting ELSE causes unmatched rows to evaluate to NULL. Always provide an explicit fallback (ELSE 'Other' or ELSE 0) unless NULL is deliberate.
03
Single Return Data Type
Every THEN and ELSE branch must return values of compatible types. Mixing integers and text strings causes a runtime type mismatch error.
04
Prefer Searched CASE
Simple CASE only handles exact equality and cannot test for NULL. Searched CASE handles ranges, IS NULL checks, and multi-column boolean criteria.
05
COUNT(CASE) Omit ELSE
When counting conditional events, omit ELSE so non-matches become NULL. Because COUNT() skips NULLs, it counts only matching occurrences.
06
Cast Numerics to Prevent Chopping
Integer division truncates decimals silently. Cast at least one operand (val::NUMERIC / divisor) to preserve fractional precision.

Quick Reference: Conditional & Casting Cheatsheet

Complete PostgreSQL conditional syntax and explicit conversion index with interactive ▶ Run links.

CASE WHEN PATTERNS
Simple CASE (Discrete mapping)▶ Run
SELECT CASE 'Gold' WHEN 'Gold' THEN 'VIP' ELSE 'Regular' END;
Searched CASE (Range banding)▶ Run
SELECT CASE WHEN 75000 >= 50000 THEN 'Tier 1' ELSE 'Tier 2' END;
Multi-Branch CASE (Waterfall order)▶ Run
SELECT CASE WHEN 85 >= 90 THEN 'A' WHEN 85 >= 75 THEN 'B' ELSE 'C' END;
Missing ELSE Default (Returns NULL)▶ Run
SELECT CASE WHEN 1 = 2 THEN 'Match' END;
EXPLICIT TYPE CASTING
ANSI CAST (Standard syntax)▶ Run
SELECT CAST(12345 AS TEXT);
PostgreSQL :: Shorthand▶ Run
SELECT 12345::TEXT;
Numeric to INT (Rounds to nearest)▶ Run
SELECT 1499.95::INT, 1499.10::INT;
Float Division Shield▶ Run
SELECT 5::NUMERIC / 2;

Take-Home Challenge: 7 Queries on RetailMart

Apply today's CASE WHEN and casting techniques in the playground, then check your counts against the ones given.

01
VIP Spender Flags
From customers.customers, show customer_id, full name, and classify into 'High Priority VIP' (Platinum, Gold: 10,194 customers) or 'General Member' (39,806).
02
Custom Order Priority
From sales.orders, order transactions prioritizing 'Cancelled' (1), 'Failed' (2), 'Processing' (3), and others (4).
03
Product Price Bins
From products.products, classify price into 'Budget' (< ₹1,000), 'Mid-Range' (₹1,000–₹10,000), and 'Premium' (> ₹10,000): 848, 3,239 and 1,949 products.
04
Safe Float Margin
From products.products, calculate profit margin percentage casting numerator to numeric: (price - cost_price)::NUMERIC / price * 100.
05
Shipment SLA Tiers
From sales.shipments, calculate delivered_date - shipped_date and classify into Express (≤ 2 days: 18,058) vs Standard. Handle NULLs cleanly: 14,982 parcels have no delivered_date yet.
06
Employee Salary Bands
From stores.employees, classify monthly salary into Executive (≥ ₹1,00,000), Senior (≥ ₹60,000), and General: 578, 479 and 1,943 employees.
07
Currency Rupee Display
Format product prices with Indian currency prefix: '₹ ' || TO_CHAR(price, 'FM99,99,999.00'). Order by price descending.
✓
Ready to Execute?
Run each challenge in the interactive playground. Verify your results and review execution output.

Your SQL Journey: Session 11 Completed

Track your progress across the 59-session SQL course.

MODULE 1 S01–S08: Foundation & Sorting COMPLETED ✓
MODULE 2 · S09–S10 Strings & Dates COMPLETED ✓
MODULE 2 · S11 Conditional Logic & Casting YOU ARE HERE ●
MODULE 2 · S12 NULL Handling & 3VL UP NEXT →

Next Session Preview: NULL Handling & 3VL

Coming next in Module 2: Defensive SQL & Three-Valued Logic.

NULL Handling: COALESCE, NULLIF & Three-Valued Logic
MODULE 2 · SESSION 12
Master defensive NULL handling with COALESCE() fallbacks, NULLIF() zero-division shields, horizontal extremes with GREATEST and LEAST, three-valued logic truth tables, and the lethal NOT IN (NULL) trap.
View Live Schedule → Review From Beginning ↺
→ next   ← back   F fullscreen   H hide bars   N notes
1 / 23