Welcome back. You now have two advanced tools that separate beginners from job-ready DBAs:
CTEs and window functions.
In the real world, you will constantly be asked to translate messy business rules into clean, safe SQL:
“Flag risky records,” “Map internal codes to readable labels,” “Create tiers,” “Handle NULLs,”
“Detect anomalies,” and “Produce a report that leadership can understand in one glance.”
That is exactly what CASE expressions are for.
Lesson description: You will learn how CASE works (simple vs searched CASE),
how DBAs use CASE to make reports readable, how to build safe classifications and flags,
how to handle NULL values correctly, how to avoid common mistakes (overlapping conditions, implicit conversions),
and how to combine CASE with window functions for professional-quality reporting and anomaly detection.
A CASE expression is SQL’s built-in way to write conditional logic:
“If this is true, return that; otherwise return something else.”
DBAs use CASE to:
DBA rule: CASE should make your output clearer and safer, not more confusing.
If a CASE becomes too complex, break logic into CTE stages.
Use this when you are matching a single column to specific values.
SELECT
Status,
CASE Status
WHEN 'NEW' THEN 'New Booking'
WHEN 'CONFIRMED' THEN 'Confirmed Booking'
WHEN 'CANCELLED' THEN 'Cancelled Booking'
ELSE 'Other / Unknown'
END AS StatusLabel
FROM dbo.Booking;
This is the most common for DBA work. You can test ranges, NULLs, patterns, and multiple columns.
SELECT
TotalDue,
CASE
WHEN TotalDue >= 5000 THEN 'High Value'
WHEN TotalDue >= 1000 THEN 'Medium Value'
WHEN TotalDue > 0 THEN 'Low Value'
ELSE 'Zero / Unknown'
END AS ValueTier
FROM Sales.SalesOrderHeader;
DBA best practice: Put conditions in correct order (highest threshold first) to avoid incorrect classification.
NULLs are normal in real data. DBAs do not let NULLs silently ruin reporting.
CASE is often used to make NULL behavior explicit.
SELECT
c.CustomerID,
CASE
WHEN p.BusinessEntityID IS NULL THEN 'No Person Record (Store/Other)'
ELSE p.FirstName + ' ' + p.LastName
END AS CustomerDisplayName
FROM Sales.Customer AS c
LEFT JOIN Person.Person AS p
ON c.PersonID = p.BusinessEntityID;
DBAs often build reports that highlight missing key fields.
SELECT
c.CustomerID,
ea.EmailAddress,
CASE
WHEN ea.EmailAddress IS NULL OR LTRIM(RTRIM(ea.EmailAddress)) = '' THEN 1
ELSE 0
END AS IsEmailMissing
FROM Person.EmailAddress AS ea
RIGHT JOIN Person.Person AS p
ON ea.BusinessEntityID = p.BusinessEntityID
RIGHT JOIN Sales.Customer AS c
ON c.PersonID = p.BusinessEntityID;
DBA note: In a real application database, “missing required data” can be a root cause of failed processes.
CASE is commonly used to encode business decisions in reports.
Your output should be easy for a non-technical person to interpret.
This is a realistic business request: classify customers by value.
;WITH CustomerSpend AS
(
SELECT
soh.CustomerID,
SUM(soh.TotalDue) AS TotalSpent
FROM Sales.SalesOrderHeader AS soh
GROUP BY soh.CustomerID
)
SELECT
cs.CustomerID,
cs.TotalSpent,
CASE
WHEN cs.TotalSpent >= 100000 THEN 'Platinum'
WHEN cs.TotalSpent >= 50000 THEN 'Gold'
WHEN cs.TotalSpent >= 10000 THEN 'Silver'
WHEN cs.TotalSpent > 0 THEN 'Bronze'
ELSE 'No Spend'
END AS CustomerTier
FROM CustomerSpend AS cs
ORDER BY cs.TotalSpent DESC;
DBA best practice: Explicit thresholds, explicit “No Spend,” and a clear order for evaluation.
DBAs often build a “risk flag” column that highlights rows requiring attention.
SELECT TOP (200)
soh.SalesOrderID,
soh.OrderDate,
soh.SubTotal,
soh.Freight,
soh.TotalDue,
CASE
WHEN soh.SubTotal <= 0 THEN 'Data Issue: SubTotal <= 0' WHEN soh.Freight / NULLIF(soh.SubTotal, 0) >= 0.25 THEN 'Risk: High Freight %'
WHEN soh.TotalDue >= 10000 THEN 'Review: Very High Order'
ELSE 'Normal'
END AS ReviewFlag
FROM Sales.SalesOrderHeader AS soh
ORDER BY soh.OrderDate DESC;
DBA note: Flags like this are used for auditing, finance checks, and operational review queues.
DBAs often need “counts by category” or “how many are missing required fields.”
CASE can be used inside SUM/COUNT to do conditional aggregates.
SELECT
SUM(CASE WHEN soh.TotalDue >= 5000 THEN 1 ELSE 0 END) AS HighValueOrders,
SUM(CASE WHEN soh.TotalDue >= 1000 AND soh.TotalDue < 5000 THEN 1 ELSE 0 END) AS MediumValueOrders, SUM(CASE WHEN soh.TotalDue > 0 AND soh.TotalDue < 1000 THEN 1 ELSE 0 END) AS LowValueOrders,
COUNT(*) AS TotalOrders
FROM Sales.SalesOrderHeader AS soh;
DBA tip: Conditional aggregation is one of the cleanest ways to produce KPI summaries.
Combining CASE with window functions creates advanced reports without complicated stored procedures.
Example: classify customers, then rank them within tiers.
;WITH CustomerSpend AS
(
SELECT
soh.CustomerID,
SUM(soh.TotalDue) AS TotalSpent
FROM Sales.SalesOrderHeader AS soh
GROUP BY soh.CustomerID
),
Tiered AS
(
SELECT
cs.CustomerID,
cs.TotalSpent,
CASE
WHEN cs.TotalSpent >= 100000 THEN 'Platinum'
WHEN cs.TotalSpent >= 50000 THEN 'Gold'
WHEN cs.TotalSpent >= 10000 THEN 'Silver'
WHEN cs.TotalSpent > 0 THEN 'Bronze'
ELSE 'No Spend'
END AS Tier
FROM CustomerSpend AS cs
),
Ranked AS
(
SELECT
t.CustomerID,
t.TotalSpent,
t.Tier,
ROW_NUMBER() OVER (PARTITION BY t.Tier ORDER BY t.TotalSpent DESC, t.CustomerID ASC) AS TierRank
FROM Tiered AS t
)
SELECT
r.Tier,
r.TierRank,
r.CustomerID,
r.TotalSpent
FROM Ranked AS r
WHERE r.Tier IN ('Platinum','Gold','Silver')
AND r.TierRank <= 20
ORDER BY r.Tier, r.TierRank;
DBA outcome: You now have “Top 20 customers per tier” with clean, auditable logic.
If your conditions overlap, rows can be classified incorrectly.
Fix by ordering conditions from most specific/highest threshold to lowest.
If you omit ELSE, SQL returns NULL for unmatched rows.
DBAs usually include ELSE for predictable outputs (even if it’s “Unknown”).
CASE returns one data type. If one branch returns text and another returns numeric, SQL Server may convert unexpectedly.
Keep outputs consistent (all numeric, or all text). Cast explicitly when needed.
You can use CASE in WHERE, but it often harms clarity.
DBAs typically compute the CASE in a CTE, then filter on the computed column.
Do these in AdventureWorks and save the scripts:
Next, you will learn how DBAs handle date/time correctly—one of the most common sources of bugs,
incorrect reports, and production incidents. You will learn precision, time zones, and safe filtering patterns.
Not a member yet? Register now
Are you a member? Login now