Собесов

Amazon: клиенты, купившие iPhone, но не Airpods

SQLАнтиджойнЛёгкаяJunior

Условие

Дана таблица Orders(customer_id, product_name, order_date). Напишите запрос, выявляющий всех клиентов, купивших iPhone, но не купивших Airpods, чтобы команда маркетинга могла отправить им предложение.

Решение

Подход

Классический «антиджойн»: набор A минус набор B. Три эквивалентных способа: NOT EXISTS, LEFT JOIN ... IS NULL, EXCEPT.

Реализация

-- Вариант 1: NOT EXISTS (предпочтительно, читаемо)
SELECT DISTINCT o.customer_id
FROM Orders o
WHERE o.product_name = 'iPhone'
  AND NOT EXISTS (
    SELECT 1 FROM Orders o2
    WHERE o2.customer_id = o.customer_id
      AND o2.product_name = 'Airpods'
  );
 
-- Вариант 2: EXCEPT
SELECT DISTINCT customer_id FROM Orders WHERE product_name = 'iPhone'
EXCEPT
SELECT DISTINCT customer_id FROM Orders WHERE product_name = 'Airpods';
 
-- Вариант 3: LEFT JOIN ... IS NULL
SELECT DISTINCT i.customer_id
FROM Orders i
LEFT JOIN Orders a
  ON a.customer_id = i.customer_id AND a.product_name = 'Airpods'
WHERE i.product_name = 'iPhone'
  AND a.customer_id IS NULL;

Подводные камни

  1. Без DISTINCT будет дублирование, если клиент купил iPhone несколько раз.
  2. Чувствительность к регистру: 'iPhone' vs 'iphone' — лучше LOWER().
  3. Если айфонов несколько моделей (iPhone 14, iPhone 15) — LIKE 'iPhone%'.
  4. NOT IN опасен при NULL в подзапросе — он вернёт пустоту. NOT EXISTS в этом случае безопаснее.

Эталонный ответ

NOT EXISTS или EXCEPT на customer_id, отфильтровав по продукту в каждой ветке.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти