Подзапросы vs присоединения
Говорят, что девять из десяти аналитиков, решая одну и ту же задачу, напишут разный код, который выдаст одинаковый результат. Но самые большие споры разгораются между «адептами» подзапросов и присоединений. На практике вы наверняка столкнётесь с теми и другими.
Представим, как может выглядеть этот спор. Любитель
JOIN-ов скажет: «Зачем использовать подзапросы? Огромный запутанный код, в котором невозможно разобраться. А чужой код с подзапросами — вообще потёмки».На что поклонник подзапросов ответит: «Какие присоединения? В базе три таблицы по полтора миллиона записей. Можно трижды выпить кофе, пока они соединятся. Лучше сделать подзапрос и сразу отсечь всё лишнее».
У каждого подхода свои плюсы и минусы — выбор зависит от данных и доступных вам мощностей. Главное — отыскать баланс: быстро выгрузить необходимые данные и сделать это с помощью оптимального кода.
Строгих правил, какого подхода придерживаться, нет. Иногда полезнее их комбинировать: и присоединять таблицы, и добавлять подзапросы. Как это реализовать на практике, мы покажем в следующем уроке.
Давайте проверим ваше аналитическое чутьё. Дано: таблица с выручкой магазина и таблица с расходами на рекламные кампании. Вас просят отобразить выручку и сумму расходов на рекламу по месяцам, но при условии: сумма расходов на рекламу должна превышать среднее месячное значение за прошлый год.
Декомпозируем задачу
Лучше начинать с декомпозиции. Выделим подзадачи:
- Сформировать помесячную выручку.
- Посчитать расходы на рекламу по месяцам.
- Найти среднее значение расходов на рекламу и отфильтровать таблицу.
- Представить результат.
Теперь пора определиться со способом решения задачи.
Как мы уже говорили, правил нет: выбирайте способ сами.
Ниже разберём, как сочетать подзапросы и присоединения, и покажем два подхода.
Сначала подзапросы
Построим три подзапроса:
- сгруппируем данные по месяцу и посчитаем выручку;
- вычислим среднее значение расходов на рекламу;
- сгруппируем расходы на рекламу по месяцам, посчитаем сумму, а затем отфильтруем с помощью
HAVINGпо найденному среднему.
Подзапросы сформируют две таблицы: с выручкой и с расходами.
Таблица с выручкой
Таблица с расходами, отфильтрованная оператором
HAVINGТаблицы, сформированные подзапросами, можно присоединять друг к другу как обычные. Объединить их можно по значению месяца. Используем
LEFT JOIN: в этом случае сохранятся все данные из таблицы с выручкой, а в записях с месяцами, в которых расходы не превышают среднее, появятся пропуски.Начинаем с присоединений
Задачу можно решить и по-другому: сначала объединить таблицы, а затем отфильтровать нужные данные. Подзадачи остаются прежними — меняются лишь промежуточные действия.
Присоединим две таблицы друг к другу, сгруппируем по месяцу и вычислим выручку и расходы. В итоге получим такую таблицу:
Остался последний пункт — отфильтровать итоговую выручку по рассчитанному среднему.
Добавим отображение этой таблицы в подзапрос и с помощью конструкции с
CASE сделаем новое поле с условием: если значение меньше указанного (тут добавим подзапрос с расчётом среднего), то значение останется в поле, если нет — вместо него будет NULL.Результат совпадает с таблицей, сформированной первым способом:
Это не предел возможностей: подходов к решению одной задачи может быть много.
В следующем уроке мы разберём несколько примеров с кодом, чтобы вы научились сочетать подзапросы и присоединения на практике.