Memra

Non-Correlated Subqueries: IN / NOT IN

Use a subquery that runs once to produce a value set, then filter the outer query with IN / NOT IN — the set-membership idiom for "is this row in (or not in) that set?".

A query inside a query

A subquery is a SELECT nested inside another statement's WHERE (or HAVING). A non-correlated (regular) subquery is the simple kind: the inner query is self-contained, runs once, and hands its result up to the outer query like a precomputed list of values. The outer query then uses IN or NOT IN to test membership.

- x IN (subquery) — true when x equals *any* value the subquery returned. - x NOT IN (subquery) — true when x matches *none* of them.

The inner SELECT must return exactly one column (the values being compared).

When a subquery, when a join?

The rule the exam quotes (6-7): *anything written as a subquery can be rewritten as a join, but not vice-versa.* The reason is projection: a join can display columns from every table; a subquery's inner columns cannot appear in the outer SELECT — the subquery is a *filter only*. So:

- Need to display a column from the other table? → join. - Only need the other table to filter the outer rows? → either works; the subquery often reads more clearly ("keep students whose id appears in registrations").

Worked example: qualified for one course, not another (exam 6-27)

*Question:* which instructors are qualified to teach COMP 378 but not COMP 456? List id and name.

The "qualified for X" part is a join (instructorsqualifiedcourses). The "and not for Y" part is naturally a NOT IN against the set of instructors qualified for COMP 456:

SELECT i.instr_id, i.name
FROM   instructors i
JOIN   qualified q ON q.instr_id = i.instr_id
JOIN   courses  c ON c.course_id = q.course_id
WHERE  c.code = 'COMP 378'
  AND  i.instr_id NOT IN (
        SELECT q2.instr_id
        FROM   qualified q2
        JOIN   courses c2 ON c2.course_id = q2.course_id
        WHERE  c2.code = 'COMP 456');

The inner query runs once, returning the ids of every instructor qualified for COMP 456. The outer query keeps COMP 378 instructors whose id is not in that set. Result: Dr. Olsen (qualified for 378, but not for 456).

The NOT IN / NULL trap

One sharp edge: if the subquery's value set contains a NULL, NOT IN returns *no rows at all* (every comparison becomes UNKNOWN). When the inner column is nullable, guard it (WHERE col IS NOT NULL) or prefer NOT EXISTS (next lesson), which is null-safe.

NORMAL ~/memra/learn/comp-378/subqueries-in-notin utf-8 LF