Есть таблицы payments(user_id) и refunds(user_id). Нужно получить пользователей, у которых был платёж, но не было ни одного возврата. Какой запрос корректнее всего описывает задачу?

ASELECT user_id FROM payments INTERSECT SELECT user_id FROM refunds
BSELECT p.user_id FROM payments p INNER JOIN refunds r ON p.user_id = r.user_id
CSELECT user_id FROM payments EXCEPT SELECT user_id FROM refunds
DSELECT user_id FROM payments UNION ALL SELECT user_id FROM refunds
Правильный ответ. EXCEPT возвращает разность множеств: значения из первой выборки, которых нет во второй.

Разбор

Для условия «платили, но не возвращали» нужна именно разность наборов пользователей, и EXCEPT делает это напрямую на уровне множеств. INTERSECT и INNER JOIN дают пересечение — пользователей, у которых были и платежи, и возвраты, что прямо противоположно задаче. UNION ALL объединит обе таблицы и не отфильтрует возвраты. Альтернативой EXCEPT может быть LEFT JOIN ... WHERE r.user_id IS NULL или NOT IN, но именно EXCEPT короче всего описывает разность.

Проверь себя · 1/3разбор после ответа
В таблицах orders и users есть одноимённые столбцы: user_id, updated_at, status. Аналитик пишет SELECT * FROM orders NATURAL JOIN users. Что произойдёт?
Тренировать SQL в Telegram

Ещё вопросы по теме «JOIN и операции множеств»