runtime
25 / 88

lesson 25 Joins & sets · intermediate

ON versus WHERE in a LEFT JOIN

Place filters carefully when preserving unmatched rows.

the idea

In a LEFT JOIN, a condition in ON decides which right-side rows match; unmatched left rows are still kept. The same condition in WHERE runs after the join and removes rows whose right side is NULL, turning the LEFT JOIN back into an inner join.

Dataset: Healthcare

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.

providers6 columns · 460 rows
provider_idnumber · unique idfull_nametextspecialtytextclinic_nametextcitytextstatetext
1Amara MehtaFamily MedicineProvidence Family PracticeProvidenceRI
2Alice HillFamily MedicineNimbus Health CenterAtlantaGA
3Ryan ShahNephrologyCleveland Community ClinicClevelandOH
4Sofia LeeFamily MedicineAlbuquerque Community ClinicAlbuquerqueNM
5Joseph HowardFamily MedicinePrism Health CenterNew YorkNY
6Anika ScottPediatricsSolar Health CenterIndianapolisIN
provider_idnumber · unique id
1
full_nametext
Amara Mehta
specialtytext
Family Medicine
clinic_nametext
Providence Family Practice
citytext
Providence
statetext
RI
provider_idnumber · unique id
2
full_nametext
Alice Hill
specialtytext
Family Medicine
clinic_nametext
Nimbus Health Center
citytext
Atlanta
statetext
GA
provider_idnumber · unique id
3
full_nametext
Ryan Shah
specialtytext
Nephrology
clinic_nametext
Cleveland Community Clinic
citytext
Cleveland
statetext
OH
provider_idnumber · unique id
4
full_nametext
Sofia Lee
specialtytext
Family Medicine
clinic_nametext
Albuquerque Community Clinic
citytext
Albuquerque
statetext
NM
provider_idnumber · unique id
5
full_nametext
Joseph Howard
specialtytext
Family Medicine
clinic_nametext
Prism Health Center
citytext
New York
statetext
NY
provider_idnumber · unique id
6
full_nametext
Anika Scott
specialtytext
Pediatrics
clinic_nametext
Solar Health Center
citytext
Indianapolis
statetext
IN

first 6 of 460 rows · your queries use all of them

encounters9 columns · 20,447 rows
encounter_idnumber · unique idpatient_idnumber · links to patientsprovider_idnumber · links to providersencounter_classtextstart_atdate & timeend_atdate & timereason_codetexttotal_costdecimalpayer_paiddecimal
114ambulatory2022-08-07 13:00:002022-08-07 13:24:45T78.40XA175.6159.38
214telehealth2022-10-12 11:15:002022-10-12 11:59:48E11.9110.0295.53
3174telehealth2023-05-12 11:30:002023-05-12 12:13:27E11.983.6874.77
41349ambulatory2023-12-17 08:15:002023-12-17 08:39:33E11.9198.23187.3
514telehealth2024-05-09 16:45:002024-05-09 17:29:01E66.9115.0898.4
614ambulatory2024-09-07 13:00:002024-09-07 13:27:30E66.9153.61142.99
encounter_idnumber · unique id
1
patient_idnumber · links to patients
1
provider_idnumber · links to providers
4
encounter_classtext
ambulatory
start_atdate & time
2022-08-07 13:00:00
end_atdate & time
2022-08-07 13:24:45
reason_codetext
T78.40XA
total_costdecimal
175.6
payer_paiddecimal
159.38
encounter_idnumber · unique id
2
patient_idnumber · links to patients
1
provider_idnumber · links to providers
4
encounter_classtext
telehealth
start_atdate & time
2022-10-12 11:15:00
end_atdate & time
2022-10-12 11:59:48
reason_codetext
E11.9
total_costdecimal
110.02
payer_paiddecimal
95.53
encounter_idnumber · unique id
3
patient_idnumber · links to patients
1
provider_idnumber · links to providers
74
encounter_classtext
telehealth
start_atdate & time
2023-05-12 11:30:00
end_atdate & time
2023-05-12 12:13:27
reason_codetext
E11.9
total_costdecimal
83.68
payer_paiddecimal
74.77
encounter_idnumber · unique id
4
patient_idnumber · links to patients
1
provider_idnumber · links to providers
349
encounter_classtext
ambulatory
start_atdate & time
2023-12-17 08:15:00
end_atdate & time
2023-12-17 08:39:33
reason_codetext
E11.9
total_costdecimal
198.23
payer_paiddecimal
187.3
encounter_idnumber · unique id
5
patient_idnumber · links to patients
1
provider_idnumber · links to providers
4
encounter_classtext
telehealth
start_atdate & time
2024-05-09 16:45:00
end_atdate & time
2024-05-09 17:29:01
reason_codetext
E66.9
total_costdecimal
115.08
payer_paiddecimal
98.4
encounter_idnumber · unique id
6
patient_idnumber · links to patients
1
provider_idnumber · links to providers
4
encounter_classtext
ambulatory
start_atdate & time
2024-09-07 13:00:00
end_atdate & time
2024-09-07 13:27:30
reason_codetext
E66.9
total_costdecimal
153.61
payer_paiddecimal
142.99

first 6 of 20,447 rows · your queries use all of them

patients9 columns · 3,200 rows
patient_idnumber · unique idfirst_nametextlast_nametextsextextbirth_datedatecitytextstatetextinsurance_typetextdeceased_datetext
1SaraFosterM1972-05-08BaltimoreMDmedicaidNULL
2AnikaJacksonM1953-07-10BaltimoreMDmedicareNULL
3JessicaHughesF2010-12-24NewarkNJmedicaidNULL
4RahulGonzalezF2023-04-04Los AngelesCAcommercialNULL
5JasmineMillerM1996-08-07ManchesterNHmedicaidNULL
6EmmaIbrahimM1933-12-10New YorkNYmedicareNULL
patient_idnumber · unique id
1
first_nametext
Sara
last_nametext
Foster
sextext
M
birth_datedate
1972-05-08
citytext
Baltimore
statetext
MD
insurance_typetext
medicaid
deceased_datetext
NULL
patient_idnumber · unique id
2
first_nametext
Anika
last_nametext
Jackson
sextext
M
birth_datedate
1953-07-10
citytext
Baltimore
statetext
MD
insurance_typetext
medicare
deceased_datetext
NULL
patient_idnumber · unique id
3
first_nametext
Jessica
last_nametext
Hughes
sextext
F
birth_datedate
2010-12-24
citytext
Newark
statetext
NJ
insurance_typetext
medicaid
deceased_datetext
NULL
patient_idnumber · unique id
4
first_nametext
Rahul
last_nametext
Gonzalez
sextext
F
birth_datedate
2023-04-04
citytext
Los Angeles
statetext
CA
insurance_typetext
commercial
deceased_datetext
NULL
patient_idnumber · unique id
5
first_nametext
Jasmine
last_nametext
Miller
sextext
M
birth_datedate
1996-08-07
citytext
Manchester
statetext
NH
insurance_typetext
medicaid
deceased_datetext
NULL
patient_idnumber · unique id
6
first_nametext
Emma
last_nametext
Ibrahim
sextext
M
birth_datedate
1933-12-10
citytext
New York
statetext
NY
insurance_typetext
medicare
deceased_datetext
NULL

first 6 of 3,200 rows · your queries use all of them

appointments7 columns · 19,438 rows
appointment_idnumber · unique idpatient_idnumber · links to patientsprovider_idnumber · links to providersbooked_atdate & timescheduled_startdate & timestatustextencounter_idnumber · links to encounters
1142022-08-04 10:00:002022-08-04 13:00:00cancelledNULL
2142022-08-04 10:00:002022-08-07 13:00:00completed1
3142022-09-29 09:15:002022-10-12 11:15:00completed2
41742023-04-10 06:30:002023-05-12 11:30:00completed3
513492023-12-08 05:15:002023-12-17 08:15:00completed4
6142024-04-22 12:45:002024-05-09 16:45:00completed5
appointment_idnumber · unique id
1
patient_idnumber · links to patients
1
provider_idnumber · links to providers
4
booked_atdate & time
2022-08-04 10:00:00
scheduled_startdate & time
2022-08-04 13:00:00
statustext
cancelled
encounter_idnumber · links to encounters
NULL
appointment_idnumber · unique id
2
patient_idnumber · links to patients
1
provider_idnumber · links to providers
4
booked_atdate & time
2022-08-04 10:00:00
scheduled_startdate & time
2022-08-07 13:00:00
statustext
completed
encounter_idnumber · links to encounters
1
appointment_idnumber · unique id
3
patient_idnumber · links to patients
1
provider_idnumber · links to providers
4
booked_atdate & time
2022-09-29 09:15:00
scheduled_startdate & time
2022-10-12 11:15:00
statustext
completed
encounter_idnumber · links to encounters
2
appointment_idnumber · unique id
4
patient_idnumber · links to patients
1
provider_idnumber · links to providers
74
booked_atdate & time
2023-04-10 06:30:00
scheduled_startdate & time
2023-05-12 11:30:00
statustext
completed
encounter_idnumber · links to encounters
3
appointment_idnumber · unique id
5
patient_idnumber · links to patients
1
provider_idnumber · links to providers
349
booked_atdate & time
2023-12-08 05:15:00
scheduled_startdate & time
2023-12-17 08:15:00
statustext
completed
encounter_idnumber · links to encounters
4
appointment_idnumber · unique id
6
patient_idnumber · links to patients
1
provider_idnumber · links to providers
4
booked_atdate & time
2024-04-22 12:45:00
scheduled_startdate & time
2024-05-09 16:45:00
statustext
completed
encounter_idnumber · links to encounters
5

first 6 of 19,438 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.

  1. Put the filter in ON. Run this. LEFT JOIN with telehealth in ON keeps every provider; counts are zero when none match.

    step-1.sql
    SELECT p.provider_id, COUNT(e.encounter_id) AS telehealth_visits
    FROM providers p
    LEFT JOIN encounters e
      ON e.provider_id = p.provider_id
      AND e.encounter_class = 'telehealth'
    GROUP BY p.provider_id
    ORDER BY telehealth_visits
    LIMIT 10;
  2. Same filter in WHERE instead. Run this. WHERE telehealth removes providers with no matching encounter—like an inner join.

    step-2.sql
    SELECT COUNT(DISTINCT p.provider_id) AS providers_left
    FROM providers p
    LEFT JOIN encounters e ON e.provider_id = p.provider_id
    WHERE e.encounter_class = 'telehealth';
  3. Put it together. The lesson's pattern in one query.the pattern

    example.sql
    SELECT p.provider_id, COUNT(e.encounter_id) AS telehealth_visits
    FROM providers p
    LEFT JOIN encounters e
      ON e.provider_id = p.provider_id
      AND e.encounter_class = 'telehealth'
    GROUP BY p.provider_id;

common mistake

LEFT JOIN encounters e ON … WHERE e.encounter_class = 'emergency' drops every provider without an emergency visit.

challenge 1

Return provider_id and emergency_visits for every provider: the number of their emergency encounters, 0 when none.

what to return

Columns
provider_idemergency_visits in this order
Rows
any order
challenge-1.sql
 
To master this lesson, solve both challenges without hints and pass the concept check. 3 of 3 to go.
ON versus WHERE in a LEFT JOIN — Joins & sets · Runtime