CASE
Sometimes you'll need to do different things based on if a value is NULL
or not.
One useful keyword for that is CASE
.
Before we look at that with NULL
, let's look at CASE
by itself.
If-Then Logic
CASE
gives you "if this then that" type of logic.
Let's look at an example with the numbers
table.
column_name | type |
---|---|
x | INTEGER |
SELECT
x,
CASE
WHEN x % 2 = 0 THEN 'even'
ELSE 'odd'
END AS parity
FROM numbers;
x INTEGER | parity TEXT |
---|---|
1 | odd |
2 | even |
3 | odd |
4 | even |
5 | odd |
Case expressions are delimited by the keywords CASE
and END
.
In between, you can have 1 or more WHEN THEN
clauses.
The WHEN
expression must evaluate to a boolean.
If TRUE
, the corresponding THEN
expression becomes the chosen value of the case expression.
Optionally, you can have an ELSE
clause with a final expression to be chosen if none of the other WHEN
clauses are TRUE
.
Notice that I call it a "case expression" and not a "case clause".
This is an important distinction because expressions are things that go inside a clause, like in a SELECT
or WHERE
clause.
Here is an example with multiple WHEN
s where we play the famous children's game "FizzBuzz".
SELECT
x,
CASE
WHEN x % 15 = 0 THEN 'FizzBuzz'
WHEN x % 5 = 0 THEN 'Buzz'
WHEN x % 3 = 0 THEN 'Fizz'
ELSE x
END AS output
FROM numbers;
error: invalid input syntax for type integer: "FizzBuzz"
Wait!! There's an error?
Type Casting
The problem with the above example is that a CASE
expression expects every case to return the same type.
We can't have some cases return text and some integers.
So, we need the ability to convert x
to TEXT
instead of INTEGER
.
You can do that with CAST
.
It looks like this: CAST(some_value AS OTHER_TYPE)
.
SELECT
x,
CASE
WHEN x % 15 = 0 THEN 'FizzBuzz'
WHEN x % 5 = 0 THEN 'Buzz'
WHEN x % 3 = 0 THEN 'Fizz'
ELSE CAST(x AS TEXT)
END AS output
FROM numbers;
x INTEGER | output TEXT |
---|---|
1 | 1 |
2 | 2 |
3 | Fizz |
4 | 4 |
5 | Buzz |
Postgres-Specific Casting
CAST
is part of standardized SQL.
It should work on any SQL database.
However, Postgres has its own alternative.
Instead of CAST(x AS TEXT)
, you can use x::TEXT
.
SELECT
x,
CASE
WHEN x % 15 = 0 THEN 'FizzBuzz'
WHEN x % 5 = 0 THEN 'Buzz'
WHEN x % 3 = 0 THEN 'Fizz'
ELSE x::TEXT
END AS output
FROM numbers;
x INTEGER | output TEXT |
---|---|
1 | 1 |
2 | 2 |
3 | Fizz |
4 | 4 |
5 | Buzz |
This is something in programming that we call "syntactic sugar," which is a more convenient/appealing but functionally equivalent way to express something.
You can use either CAST
or the ::
operator with Postgres, as they are interchangeable.
I recommend using CAST
.
Generally, the standard method of doing things is more beneficial to know for the long-term because that knowledge will transfer when you use a different SQL database.
Filling NULL
Values
Sometimes we want to change NULL
to something else, either because NULL
's properties are confusing/inconvenient or because we want to fill it with a different value.
For example, suppose our app "Yulp" want to fill the cuisine_type
with the string "Other" instead of NULL
.
SELECT
name,
cuisine_type,
CASE
WHEN cuisine_type IS NOT NULL THEN cuisine_type
ELSE 'Other'
END AS cuisine_type_filled
FROM restaurants
WHERE delivery_fee_usd IS NOT NULL;
name VARCHAR | cuisine_type VARCHAR | cuisine_type_filled VARCHAR |
---|---|---|
Harmonious Shift | NULL | Other |
Outlying Centre | French | French |
Gently Accurate Homeownership | Taiwanese | Taiwanese |
Knowing Geography | NULL | Other |
Foolish Chapter | Greek | Greek |
Stale Spelt | Spanish | Spanish |
Diligently Grateful Pecan | Italian | Italian |
Worldly Menu | Vietnamese | Vietnamese |
Scientific Standardization | NULL | Other |
Precious Art | NULL | Other |
Coalesce
There is a nice little shortcut for CASE WHEN x IS NOT NULL THEN x ELSE 0 END
.
You can call the function coalesce(x, 0)
instead!
SELECT
name,
cuisine_type,
coalesce(cuisine_type, 'Other') AS cuisine_type_filled
FROM restaurants
WHERE delivery_fee_usd IS NOT NULL;
name VARCHAR | cuisine_type VARCHAR | cuisine_type_filled VARCHAR |
---|---|---|
Harmonious Shift | NULL | Other |
Outlying Centre | French | French |
Gently Accurate Homeownership | Taiwanese | Taiwanese |
Knowing Geography | NULL | Other |
Foolish Chapter | Greek | Greek |
Stale Spelt | Spanish | Spanish |
Diligently Grateful Pecan | Italian | Italian |
Worldly Menu | Vietnamese | Vietnamese |
Scientific Standardization | NULL | Other |
Precious Art | NULL | Other |