Skip to content
LakeBench
ProblemsCommunityPricing
Sign inStart practicing
Back
  1. Home
  2. Interview prep
  3. Customers who bought A but not B

SQL · Scenario Patterns (explain the approach, small SQL)

Customers who bought A but not B

Easysql-76
scenarioconditional-aggregationnot-existsanti-join

Question

Find customers who bought product A but never product B.

Solution

There are three clean ways. The simplest to read for a single table is conditional aggregation: count how many A rows and how many B rows each customer has, and keep customers with A above zero and B equal to zero.

Conditional aggregation

SELECT customer_id
FROM purchases
GROUP BY customer_id
HAVING SUM(CASE WHEN product = 'A' THEN 1 ELSE 0 END) > 0
   AND SUM(CASE WHEN product = 'B' THEN 1 ELSE 0 END) = 0;

One pass over the table. It scales well, and adding conditions like "A and C but not B" only needs more lines in HAVING.

EXISTS and NOT EXISTS

SELECT DISTINCT p.customer_id
FROM purchases p
WHERE p.product = 'A'
  AND NOT EXISTS (
    SELECT 1 FROM purchases b
    WHERE b.customer_id = p.customer_id AND b.product = 'B'
  );

Reads exactly like the sentence in the question. Needs DISTINCT, because a customer who bought A three times appears three times.

Set operation

SELECT customer_id FROM purchases WHERE product = 'A'
EXCEPT
SELECT customer_id FROM purchases WHERE product = 'B';

EXCEPT (called MINUS in Oracle) returns distinct rows from the first query that are not in the second. Short, and it removes duplicates for you.

What to avoid

NOT IN (SELECT customer_id ... WHERE product = 'B') fails if any customer_id in the subquery is NULL: it returns no rows. This is the NOT IN trap. Mention it, since the interviewer is likely to listen for it.

Also be careful with WHERE product = 'A' AND product <> 'B' on one table. A single row cannot be both, so it returns nothing useful. The logic has to look across rows of the same customer.

Choosing

If you only need the ids, EXCEPT is shortest. If the table is large and the question might grow, use conditional aggregation. If readability matters most, use NOT EXISTS.

🎯 Put this concept into practice

Solidify this answer with real hands-on interview drills in the browser studio.

Open related drill →
PreviousNext