В запросе нужно убрать AS из GROUP BY и квалифицировать campaign. INNER JOIN считает только совпадения, LEFT JOIN сохраняет кампании без коммуникаций; точные числа требуют исходных таблиц.
Группировка campaign и различия INNER JOIN и LEFT JOIN
В запросе нужно убрать AS из GROUP BY и квалифицировать campaign. INNER JOIN считает только совпадения, LEFT JOIN сохраняет кампании без коммуникаций; точные числа требуют исходных таблиц.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
-- 1.1 Что выведет запрос:
SELECT campaign, COUNT(*) as rows, COUNT(DISTINCT co.user_id) AS users FROM campaigns AS ca INNER JOIN communications AS co ON ca.campaign = co.campaign GROUP BY ca.campaign AS campaign
-- 1.2 Как изменится ответ, если поменять тип JOIN на LEFT? -- 1.3 Укажите порядок выполнения операторов в этом запросе.
-- 2. Таблицу campaigns починили: убрали задубливание, добавили ключ (PK). -- Провели больше кампаний, из-за багов у пользователей стали появляться неудачные попытки доставки коммуникаций, а кому-то совсем не удалось показать.
-- По отправленным на пользователей промо-кампаниям: -- 2.1 Напишите запрос, который выводит количество пользователей, успешно получивших коммуникацию, для каждой кампании. -- 2.2 Измените запрос, чтобы вывести: количество пользователей, не получивших в итоге ни одной успешной коммуникации, для каждой кампании?
Ответ
В запросе нужно убрать AS из GROUP BY и квалифицировать campaign. INNER JOIN считает только совпадения, LEFT JOIN сохраняет кампании без коммуникаций; точные числа требуют исходных таблиц.
Исправление группировки: SELECT ca.campaign, COUNT(*), COUNT(DISTINCT co.user_id) ... GROUP BY ca.campaign. Дубли campaigns размножают строки соединения, но не число DISTINCT пользователей внутри кампании. При LEFT JOIN кампания без совпадений даёт COUNT(*) = 1, а COUNT(DISTINCT co.user_id) = 0.
Логический порядок: FROM/JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.
Для второй части предположим, что успех обозначен status = 'success':
WITH deliveries AS (
SELECT campaign, user_id,
MAX(CASE WHEN status = 'success' THEN 1 ELSE 0 END) AS delivered
FROM communications
GROUP BY campaign, user_id
)
SELECT ca.campaign,
SUM(CASE WHEN d.delivered = 1 THEN 1 ELSE 0 END) AS successful_users,
SUM(CASE WHEN d.delivered = 0 THEN 1 ELSE 0 END) AS unsuccessful_users
FROM campaigns ca
LEFT JOIN deliveries d ON d.campaign = ca.campaign
GROUP BY ca.campaign;
Так повторные попытки не увеличивают число пользователей. Неуспешные здесь — пользователи с попытками, но без успеха. Чтобы учесть тех, кому не сделали ни одной попытки, нужна отдельная таблица целевой аудитории кампании.