What if you want to create a new variable using if-else conditions or want to do some aggregations based on some if-else conditions? SQL is so powerful that its CASE WHEN syntax provides you this utility.
Prerequisites:
Aggregate functions and GROUP BY: Click here to review the tutorial
Data:
For this tutorial we shall make use of the data: hospital_record
CREATE TABLE hospital_record(
patient_id int,
department varchar(20),
length_of_stay int,
last_visit_date date)
INSERT INTO
hospital_record(patient_id,department,length_of_stay,last_visit_date)
VALUES
(1001,'Cardiology',20,'12Aug2020'),
(1002,'Radiology',0,'13Feb2019'),
(1004,'Radiology',2,'31Jan2020'),
(1005,'Neurology',4,'9Aug2018'),
(1005,'Cardiology',18,'9Aug2018'),
(1004,'Neurology',65,'19Jan2020');
Our data looks as follows:
SELECT * FROM hospital_record;
Basic Syntax for CASE WHEN:
CASE WHEN <condition 1> THEN <do something> WHEN <condition 2> THEN <do something> ELSE <default value> END AS new_column
Creating a new column with CASE WHEN:
Task: Create a new column Stay_Duration based on the conditions:
if length of stay = 0 then One day visit, if length of stay for 1-15 days then Less than a fortnight and if length of stay is more than 15 days then More than a fortnight.
SELECT *,CASE WHEN length_of_stay = 0 THEN 'One day visit'
WHEN length_of_Stay <= 15 THEN 'Less than a fortnight'
ELSE 'More than a fortnight' END AS Stay_Duration
FROM hospital_record;
Our CASE WHEN block always comes with SELECT statement while creating a new column.
Task: Create Stay_Duration variable only fetch rows only for the Cardiology department.
SELECT *,CASE WHEN length_of_stay = 0 THEN 'One day visit'
WHEN length_of_Stay <= 15 THEN 'Less than a fortnight'
ELSE 'More than a fortnight' END AS Stay_Duration
FROM hospital_record
WHERE department = 'Cardiology';
Multiple conditions in CASE WHEN
Task: Create Stay_Duration variable : If department = 'Radiology' or length of stay = 0 then One day visit, if length of stay for 1-15 days then Less than a fortnight and if length of stay is more than 15 days then More than a fortnight.
SELECT *,
CASE WHEN length_of_stay = 0 OR department = 'Radiology' THEN 'One day visits'
WHEN length_of_Stay <= 15 THEN 'Less than a fortnight'
ELSE 'More than a fortnight' END AS Stay_Duration
FROM hospital_record
What if you skip the ELSE clause? (Dealing with NULL values)
If you skip the ELSE clause then NULL values can get generated like given below:
Task: Create a new column Stay_Duration based on the conditions: if length of stay = 0 then One day visit, if length of stay for 1-15 days then Less than a fortnight
SELECT *,CASE WHEN length_of_stay = 0 THEN 'One day visits'
WHEN length_of_Stay <= 15 THEN 'Less than a fortnight'
ELSE NULL END AS Stay_Duration
FROM hospital_record
Alternatively
select *,CASE WHEN length_of_stay = 0 THEN 'One day visits'
WHEN length_of_Stay <= 15 THEN 'Less than a fortnight'
END AS Stay_Duration
FROM hospital_record
Ques: How to deal with these NULL values? What if we need to remove these NULL records? Ans: Add a WHERE clause and put your CASE WHEN statement, after END write IS NOT NULL.
SELECT *,CASE WHEN length_of_stay = 0 THEN 'One day visits'
WHEN length_of_Stay <= 15 THEN 'Less than a fortnight'
END AS Stay_Duration
FROM hospital_record
WHERE CASE WHEN length_of_stay = 0 THEN 'One day visits'
WHEN length_of_Stay <= 15 THEN 'Less than a fortnight'
END IS NOT NULL
CASE WHEN and aggregate functions:
Task: For each department count the number of one_day_visits and more than one day visits
SELECT department,COUNT(CASE WHEN length_of_stay = 0 THEN 'One day visits' END) as one_day_visits_count,
COUNT(CASE WHEN length_of_Stay > 0 THEN 'Less than a fortnight' END) as long_visits_count
FROM hospital_record
GROUP BY department
Since we are aggregating at department level thus a GROUP BY clause is mandatory. For counting the number of one day visits and long duration visits we leverage COUNT function and specify the condition in CASE WHEN). Kindly note that COUNT function only counts non-NULL values.
Alternatively, since we just need to COUNT the occurence thus in THEN clause you can add any junk value.
SELECT department,COUNT(CASE WHEN length_of_stay = 0 THEN 'xyz' END) as one_day_visits_count,
COUNT(CASE WHEN length_of_Stay > 0 THEN 'xyz' END) as long_visits_count
FROM hospital_record
GROUP BY department
Task: For each department calculate the total length of stay by all the patients for one_day_visits and more.
SELECT department,SUM(CASE WHEN length_of_stay = 0 THEN 1 END) as one_day_visits_sum,
SUM(CASE WHEN length_of_Stay > 0 THEN length_of_Stay END) as long_visits_sum
FROM hospital_record
GROUP BY department
Comments