Нужно вывести по каждому заказу признак has_refund: есть ли хотя бы одна запись в refunds по этому заказу. Таблица refunds может иметь несколько строк на один заказ. Какой вариант корректен и не размножает заказы?

ASELECT o.order_id, COUNT(r.refund_id) AS has_refund FROM orders o LEFT JOIN refunds r ON r.order_id = o.order_id;
BSELECT o.order_id, (SELECT r.refund_id FROM refunds r WHERE r.order_id = o.order_id) AS has_refund FROM orders o;
CSELECT o.order_id, MAX(r.refund_id) AS has_refund FROM orders o JOIN refunds r ON r.order_id = o.order_id;
DSELECT o.order_id, CASE WHEN EXISTS (SELECT 1 FROM refunds r WHERE r.order_id = o.order_id) THEN 1 ELSE 0 END AS has_refund FROM orders o;
Правильный ответ. EXISTS внутри CASE даёт один логический ответ на строку orders и не создаёт дубликаты строк.

Разбор

LEFT JOIN к таблице refunds без агрегации размножает строки заказов, если по заказу несколько возвратов; добавление COUNT() без GROUP BY приведёт к ошибке. Скалярный подзапрос упадёт при нескольких строках на заказ. INNER JOIN с MAX() без GROUP BY тоже неверен и заодно отбросит заказы без возвратов. Конструкция CASE WHEN EXISTS (...) THEN 1 ELSE 0 END явно проверяет наличие связанной строки и всегда возвращает одно значение на заказ.

Проверь себя · 1/3разбор после ответа
Дашборд содержит две метрики на одних и тех же продажах: топ товаров по выручке за период и общая выручка за тот же период. Витрина обновляется ежедневно, и важно, чтобы фильтр по периоду был один и тот же для обеих цифр. Какой подход надёжнее защищает от рассинхронизации?
Тренировать SQL в Telegram

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