lesson 14 Calculations & data quality · intermediate
Make decisions with CASE
Choose a result for each row using conditional logic.
the idea
CASE evaluates its WHEN conditions in order and returns the first matching result; ELSE covers everything else. Put the case for missing values first so an unknown temperature is not silently labelled by ELSE.
Dataset: Weather
The tables the challenges use, with their first 6 rows. Under each column name: the kind of value it holds, and which table it links to.
daily_weather10 columns · 109,214 rows
| station_idtext · links to stations | observation_datedate · links to calendar | tmax_cdecimal | tmin_cdecimal | precipitation_mmdecimal | precip_tracenumber | snowfall_mmdecimal | snow_depth_mmdecimal | avg_wind_speed_msdecimal | peak_gust_msdecimal |
|---|---|---|---|---|---|---|---|---|---|
| USW00003131 | 2022-01-01 | 17.2 | 7.2 | 0 | 0 | NULL | NULL | 2 | 6.3 |
| USW00003131 | 2022-01-02 | 20 | 5 | 0 | 0 | NULL | NULL | 1.1 | 5.4 |
| USW00003131 | 2022-01-03 | 17.8 | 3.9 | 0 | 0 | NULL | NULL | 1.1 | 4.5 |
| USW00003131 | 2022-01-04 | 17.2 | 4.4 | 0 | 0 | NULL | NULL | 1.4 | 4.5 |
| USW00003131 | 2022-01-05 | 21.1 | 5.6 | 0 | 0 | NULL | NULL | 0.9 | 4 |
| USW00003131 | 2022-01-06 | 22.2 | 7.2 | 0 | 0 | NULL | NULL | 0.6 | 3.6 |
- station_idtext · links to stations
- USW00003131
- observation_datedate · links to calendar
- 2022-01-01
- tmax_cdecimal
- 17.2
- tmin_cdecimal
- 7.2
- precipitation_mmdecimal
- 0
- precip_tracenumber
- 0
- snowfall_mmdecimal
- NULL
- snow_depth_mmdecimal
- NULL
- avg_wind_speed_msdecimal
- 2
- peak_gust_msdecimal
- 6.3
- station_idtext · links to stations
- USW00003131
- observation_datedate · links to calendar
- 2022-01-02
- tmax_cdecimal
- 20
- tmin_cdecimal
- 5
- precipitation_mmdecimal
- 0
- precip_tracenumber
- 0
- snowfall_mmdecimal
- NULL
- snow_depth_mmdecimal
- NULL
- avg_wind_speed_msdecimal
- 1.1
- peak_gust_msdecimal
- 5.4
- station_idtext · links to stations
- USW00003131
- observation_datedate · links to calendar
- 2022-01-03
- tmax_cdecimal
- 17.8
- tmin_cdecimal
- 3.9
- precipitation_mmdecimal
- 0
- precip_tracenumber
- 0
- snowfall_mmdecimal
- NULL
- snow_depth_mmdecimal
- NULL
- avg_wind_speed_msdecimal
- 1.1
- peak_gust_msdecimal
- 4.5
- station_idtext · links to stations
- USW00003131
- observation_datedate · links to calendar
- 2022-01-04
- tmax_cdecimal
- 17.2
- tmin_cdecimal
- 4.4
- precipitation_mmdecimal
- 0
- precip_tracenumber
- 0
- snowfall_mmdecimal
- NULL
- snow_depth_mmdecimal
- NULL
- avg_wind_speed_msdecimal
- 1.4
- peak_gust_msdecimal
- 4.5
- station_idtext · links to stations
- USW00003131
- observation_datedate · links to calendar
- 2022-01-05
- tmax_cdecimal
- 21.1
- tmin_cdecimal
- 5.6
- precipitation_mmdecimal
- 0
- precip_tracenumber
- 0
- snowfall_mmdecimal
- NULL
- snow_depth_mmdecimal
- NULL
- avg_wind_speed_msdecimal
- 0.9
- peak_gust_msdecimal
- 4
- station_idtext · links to stations
- USW00003131
- observation_datedate · links to calendar
- 2022-01-06
- tmax_cdecimal
- 22.2
- tmin_cdecimal
- 7.2
- precipitation_mmdecimal
- 0
- precip_tracenumber
- 0
- snowfall_mmdecimal
- NULL
- snow_depth_mmdecimal
- NULL
- avg_wind_speed_msdecimal
- 0.6
- peak_gust_msdecimal
- 3.6
first 6 of 109,214 rows · your queries use all of them
worked example
Run these steps in order to see the idea before you write your own query. The step marked “the pattern” is what the challenges ask for. Running the example does not count toward progress.
Label days as wet or dry. Run this. CASE checks each row and returns wet when precipitation_mm is above zero, otherwise dry.
step-1.sqlSELECT station_id, observation_date, CASE WHEN precipitation_mm > 0 THEN 'wet' ELSE 'dry' END AS day_type FROM daily_weather WHERE station_id = 'USW00094728' LIMIT 15;
Handle NULL before other labels. Run this. Put IS NULL first in CASE so missing snowfall is not mistaken for zero.
step-2.sqlSELECT observation_date, snowfall_mm, CASE WHEN snowfall_mm IS NULL THEN 'not reported' WHEN snowfall_mm > 0 THEN 'snow' ELSE 'none' END AS snow FROM daily_weather WHERE station_id = 'USW00093197' LIMIT 15;
Put it together. The lesson's pattern in one query.the pattern
example.sqlSELECT station_id, observation_date, CASE WHEN precipitation_mm > 0 THEN 'wet' ELSE 'dry' END AS day_type FROM daily_weather WHERE station_id = 'USW00094728';
common mistake
CASE WHEN tmax_c < 0 THEN 'freezing' ELSE 'above freezing' END labels a missing temperature as above freezing.