runtime
29 / 88

lesson 29 Dates, strings & subqueries · intermediate

Ask whether a row exists

Test whether matching rows exist without duplicating results.

the idea

EXISTS (subquery) is true when the subquery returns at least one row; NOT EXISTS is true when it returns none. Use it to ask whether related rows exist without multiplying the outer rows the way a join would.

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.

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

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

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. Keep patients with a related row. Run this. EXISTS returns true when the subquery finds at least one inpatient encounter.

    step-1.sql
    SELECT p.patient_id
    FROM patients p
    WHERE EXISTS (
      SELECT 1
      FROM encounters e
      WHERE e.patient_id = p.patient_id AND e.encounter_class = 'inpatient'
    )
    LIMIT 10;
  2. See why join over-counts. Run this. Joining encounters repeats patients who have multiple inpatient stays.

    step-2.sql
    SELECT COUNT(*) AS joined_rows, COUNT(DISTINCT p.patient_id) AS patients
    FROM patients p
    JOIN encounters e ON e.patient_id = p.patient_id
    WHERE e.encounter_class = 'inpatient';
  3. Put it together. The lesson's pattern in one query.the pattern

    example.sql
    SELECT p.patient_id
    FROM patients p
    WHERE EXISTS (
      SELECT 1
      FROM encounters e
      WHERE e.patient_id = p.patient_id AND e.encounter_class = 'inpatient'
    );

common mistake

Joining patients to encounters to find who had an emergency visit returns a patient once per emergency visit unless you add DISTINCT.

challenge 1

Return patient_id for patients with at least one emergency encounter.

what to return

Columns
patient_id
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.
Ask whether a row exists — Dates, strings & subqueries · Runtime