Нужно вывести список пользователей, которые сделали покупку в 2025 году, без дубликатов. Какой вариант делает это корректно без DISTINCT?

ASELECT u.user_id FROM users u WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.user_id AND o.created_at >= '2025-01-01' AND o.created_at < '2026-01-01')
BSELECT u.user_id FROM users u JOIN orders o ON o.user_id = u.user_id WHERE o.created_at >= '2025-01-01' AND o.created_at < '2026-01-01'
CSELECT o.user_id FROM orders o WHERE o.created_at >= '2025-01-01' AND o.created_at < '2026-01-01' GROUP BY o.user_id HAVING COUNT(*) >= 1
DSELECT u.user_id FROM users u WHERE (SELECT MAX(o.order_id) FROM orders o WHERE o.user_id = u.user_id AND o.created_at >= '2025-01-01' AND o.created_at < '2026-01-01') IS NOT NULL
Правильный ответ. EXISTS проверяет наличие связанных строк и сохраняет по одной строке внешней таблицы — без DISTINCT.

Разбор

Если брать строки напрямую из таблицы заказов или соединять её с пользователями через JOIN, пользователь с несколькими заказами появится несколько раз — без DISTINCT или агрегации это даст дубликаты. Вариант с GROUP BY тоже опирается на агрегацию по заказам и работает не на уровне пользователей. Конструкция EXISTS проверяет наличие хотя бы одной связанной строки и не размножает строки внешней таблицы, поэтому возвращает каждого пользователя ровно один раз.

Можно заниматься бесплатно

Готовим вопросы…

Три вопроса по теме этой страницы, с объяснениями.

Продолжить в браузере

Ещё вопросы по теме «Подзапросы и CTE»