Группировка campaign и различия INNER JOIN и LEFT JOIN

В запросе нужно убрать AS из GROUP BY и квалифицировать 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;

Так повторные попытки не увеличивают число пользователей. Неуспешные здесь — пользователи с попытками, но без успеха. Чтобы учесть тех, кому не сделали ни одной попытки, нужна отдельная таблица целевой аудитории кампании.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее