SQL знаю, а задачу аналитика не решаю: как разложить сложный запрос
Вы умеете выбрать строки, соединить таблицы и посчитать сумму. Но просьба «найдите клиентов, которые вернулись после перерыва и стали покупать больше» останавливает работу. В голове появляются LAG, подзапросы и оконные функции, а понятного первого шага нет.
В такой ситуации полезно учиться собирать решение из промежуточных результатов. Разберём рабочий запрос, в котором синтаксис знаком, но правила ещё предстоит определить: руководитель хочет список клиентов, вернувшихся после долгого отсутствия, чтобы предложить им персональные условия.
Сначала договориться, кого считать вернувшимся
Фраза «после долгого отсутствия» не задаёт вычисление. Допустим, согласовано такое правило: клиент сделал оплаченный заказ в отчётном месяце, а между ним и предыдущим оплаченным заказом прошло не меньше 60 дней. В список включаем клиента один раз, по первой подходящей покупке этого месяца. Клиентов без предыдущих покупок считаем новыми и в эту выборку не включаем.
Нужно также выбрать дату наблюдения. Отменённый завтра заказ может сегодня выглядеть оплаченным. Для повторяемого отчёта сохраните, на какой момент известны статусы. Укажите часовую зону и правило измерения перерыва: календарные даты или полные сутки между моментами покупки. Вблизи границы они дают разные ответы.
Пока эти решения не приняты, длинный SQL только прячет неоднозначность. Полезный первый результат — короткое описание выходной таблицы: одна строка на клиента, дата возврата, дата предыдущей покупки, длительность перерыва и основание включения.
Назвать строки каждого промежуточного результата
Начните с таблицы оплаченных заказов: одна строка соответствует одному заказу. Если платёжных попыток несколько, сначала определите итог оплаты для заказа. Если в заказе несколько товаров, их соединение с платежами может размножить строки ещё до поиска предыдущей покупки.
Следующий результат — покупки с датой предыдущей покупки этого клиента. Здесь появляется осмысленная задача для LAG: заглянуть в предшествующую строку внутри клиента. Даты нужно упорядочить, а при совпадении времени добавить устойчивый критерий, например идентификатор заказа. Так правило перестанет зависеть от случайного порядка строк.
После этого отберите подходящие перерывы и покупки отчётного месяца. История до месяца должна участвовать в поиске предыдущей покупки. Если сначала оставить только текущий месяц, первая покупка клиента потеряет предшественника. Внешне запрос будет работать, но отвечать на другой вопрос.
Последним шагом выберите первую подходящую покупку каждого клиента. Вы получили цепочку из четырёх небольших задач. Каждую можно посмотреть отдельно, прежде чем объединять в CTE — именованные промежуточные запросы.
Учить следующий приём по тому, что требуется сохранить
Если нужен один итог на клиента, используйте группировку. Если нужно сохранить отдельные покупки и добавить рядом предыдущую дату или накопленную сумму, изучайте оконные функции. Они выполняют расчёт по связанным строкам, сохраняя строки результата.
Для задач по времени следующий важный навык — календарь. «Три последних строки» и «три последних дня» совпадают только при определённых данных. Потом полезны исторические соединения: значение тарифа или статуса надо брать на дату события, а не из сегодняшнего справочника. Затем приходят интервалы, сессии и последовательные события. Это продолжение одной идеи: прежде чем писать конструкцию, определить, какие строки должны участвовать в расчёте.
Оптимизацию добавляйте после проверки смысла. Быстрый запрос, который теряет покупки без справочника или размножает выручку, не приближает ответ. Сначала сохраните правильный небольшой результат, затем сравнивайте с ним изменения запроса и изучайте план выполнения.
Маленькие данные быстрее обнаруживают ошибку
Для нашего списка достаточно сначала придумать несколько клиентов. У одного нет прежних покупок. У другого перерыв меньше порога. У третьего он ровно на границе. Четвёртый вернулся в начале месяца, а затем купил снова. Пятый имеет отменённый заказ между двумя оплаченными. Для каждого заранее запишите, должен ли он попасть в результат и какая покупка будет основанием.
Добавьте случай с двумя заказами в один момент и покупкой непосредственно перед началом отчётного месяца. Эти строки проверят порядок и доступность истории. Если результат неверен, открывайте промежуточные таблицы: ошибка найдётся раньше, чем при чтении большого запроса целиком.
После этого проверьте, что на одного клиента действительно приходится одна строка. А уже затем запускайте расчёт на рабочем объёме. Такой набор примеров полезно хранить рядом с запросом: изменение определения метрики сразу станет видимым.
Где взять последовательную практику
Если описание результата уже понятно, но разложить его в SQL трудно, переходите к платному курсу «Продвинутый SQL: сложные запросы и задачи для собеседований». Здесь есть предварительная агрегация перед JOIN, оконные рамки, календарные периоды, исторические значения, сессии и последовательные воронки. В программе 109 SQL-задач с автоматической проверкой, модульные кейсы и итоговая витрина интернет-магазина. Вы будете тренировать именно переход от условия к проверяемому запросу. Откройте программу и посмотрите, какие темы закрывают место, где застрял ваш текущий расчёт.
Если трудность возникает раньше — непонятно, кого включать в показатель и какой вывод разрешают данные, — полезна «Практическая аналитика данных». Она развивает работу с определением метрики, качеством данных и интерпретацией. Для ближайшей практики возьмите одну расплывчатую просьбу коллеги и подготовьте к ней определение результата, цепочку промежуточных таблиц и граничные примеры. Только после этого пишите окончательный запрос.
Продолжить на практике
- Продвинутый SQL: сложные запросы и задачи для собеседований ↗
Продолжение базового SQL: сложные JOIN, оконные рамки, временные ряды, retention, воронки и рекурсивные CTE. Разбирайте примеры и пишите запросы с автоматической проверкой — от отдельных расчётов до витрины интернет-магазина.
- Практическая аналитика данных ↗
Превратите знания SQL или Python в аналитическую работу: проверяйте данные, считайте бизнес-метрики, стройте дашборды и объясняйте выводы на трёх прикладных кейсах.
