← Назад к вопросам

SQL: Пользователи без заказов

1.0 Junior🔥 171 комментариев
#Pandas и обработка данных#SQL и базы данных

Условие

Даны таблицы users и orders.

Найдите всех пользователей, которые не сделали ни одного заказа.

Покажите несколько способов решения (LEFT JOIN, NOT EXISTS, NOT IN).

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение: Найти пользователей без заказов

Способ 1: LEFT JOIN (стандартный и быстрый)

SELECT u.user_id, u.name, u.email
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE o.user_id IS NULL;

Логика: LEFT JOIN соединяет таблицы, пользователи без заказов имеют NULL в полях orders. Фильтруем WHERE o.user_id IS NULL.

Производительность: O(n log n), использует индекс на orders.user_id

Преимущества:

  • Читаемо и интуитивно
  • Хорошая производительность
  • Стандарт SQL

Способ 2: NOT EXISTS (для больших таблиц)

SELECT u.user_id, u.name, u.email
FROM users u
WHERE NOT EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.user_id = u.user_id
);

Логика: Для каждого пользователя проверяем, существует ли хотя бы один заказ. NOT EXISTS вернёт true если подзапрос не вернул ни одной строки.

Преимущества:

  • Очень читаемо
  • Меньше ошибок с NULL
  • Early exit при первом найденном заказе
  • Часто лучшая производительность на PostgreSQL/Oracle

Способ 3: NOT IN (с осторожностью!)

SELECT u.user_id, u.name, u.email
FROM users u
WHERE u.user_id NOT IN (
  SELECT DISTINCT o.user_id
  FROM orders o
  WHERE o.user_id IS NOT NULL
);

Логика: Подзапрос находит все user_id из orders, NOT IN исключает их.

ВАЖНО! Ловушка с NULL:

  • Если в orders.user_id есть NULL, NOT IN вернёт пустой результат!
  • Обязательно фильтруй WHERE o.user_id IS NOT NULL

Способ 4: GROUP BY с HAVING (для аналитики)

SELECT u.user_id, u.name, u.email, COUNT(o.order_id) as order_count
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
GROUP BY u.user_id, u.name, u.email
HAVING COUNT(o.order_id) = 0;

Преимущества:

  • Видна статистика (даже 0 заказов)
  • Расширяемо для других метрик

Сравнение подходов

СпособСкоростьЧитаемостьКогда использовать
LEFT JOINБыстроХорошоСтандартный выбор
NOT EXISTSОчень быстроОтличноБольшие таблицы
NOT INМедленнееПростоИзбегать (NULL риск)
GROUP BYЗависитХорошоНужна аналитика

Рекомендация

Используй LEFT JOIN: быстро, читаемо, стандартно, легко расширяется.

Используй NOT EXISTS: если таблица orders очень большая и индексы хорошие (особенно PostgreSQL).

Избегай NOT IN: пока не убедился что нет NULL в подзапросе!

SQL: Пользователи без заказов | PrepBro