реклама
Бургер менюБургер меню

Артем Демиденко – Аналитика для новичков: Вход в профессию дата-аналитика (страница 5)

18

– Проанализируйте пропуски и выберите подходящую стратегию обработки

– Приведите ключевые показатели к единому масштабу и формату

– Начните вести учёт всех изменений, используйте скрипты даже для простых операций

– Определите, какие процессы можно автоматизировать с помощью имеющихся инструментов

Внесённые усилия уже завтра сделают аналитику точнее, а подготовку – быстрее. Такой подход повысит доверие к результатам и упростит масштабирование. Вы создадите стандарты, которые помогут работать с новыми источниками в будущем.

В следующей главе узнаем, как превратить подготовленные данные в структурированные отчёты и понятные визуализации. Уверенный старт в подготовке – фундамент успешного анализа, иначе последующие шаги рискуют превратиться в пустую трату времени и ресурсов.

Основы SQL для аналитика

Ошибка в SQL-запросе, которая привела к срыву проекта по аналитике, обернулась бесконечными часами правок, неверными отчётами и потерей доверия коллег. Всё началось с казалось бы простой задачи: написать запрос с правильной структурой и отбором данных. Но за видимой простотой скрывалась сложная задача – подготовить квартальный отчёт, отражающий реальные результаты продаж.

Поначалу всё шло по плану. Основной таблицей была таблица с продажами, к ней через джойны подтягивали информацию о клиентах и товарах. Запрос сооружался традиционно: SELECT, FROM, WHERE, GROUP BY, ORDER BY. Но под самый дедлайн выяснилось несоответствие суммарных данных продаж с бухгалтерскими цифрами. Проблема крылась в дублировании строк из-за неправильных джойнов и неаккуратных условий фильтрации. В итоге отчёт оказался недостоверным, а сдавать его было нужно срочно.

В этой главе мы подробно разберём, как и где возникают такие ошибки, какие шаги помочь избежать провалов и как действовать, если ситуация выходит из-под контроля.

Обстоятельства срыва: взгляд изнутри

Задача звучала так: сформировать отчёт по продажам с разбивкой по регионам и категориям товаров, с возможностью фильтрации по датам и определённым сегментам клиентов. На первый взгляд, разумно было разделить работу на несколько этапов – выбрать сначала нужных клиентов, потом товары, и лишь затем агрегировать данные продаж.

В голове запрос выглядел просто: взять продажи, добавить клиентов и товары через LEFT JOIN, отфильтровать по нужному периоду. Использование LEFT JOIN казалось логичным – чтобы не потерять записи, если у продажи не оказалось связанного клиента. Этот подход казался здравым.

Но первые версии запроса выросли до нескольких сотен строк. Добавлялись подзапросы с выборкой специфических клиентов и товаров, при этом все пытались аккуратно сгруппировать данные, чтобы избежать лишних повторений.

На практике итоговые данные оказались с многократными дублированием. Из-за неверного порядка джойнов и условий фильтрации часть строк выпадала, а часть повторялась. Итог – сумма продаж оказалась завышена почти на треть. Аналитикам пришлось тратить часы на ручные проверки, а менеджеры затихли в ожидании отчёта.

Промежуточные попытки исправить ситуацию лишь усугубляли положение:

– Запрос усложнялся, обрастая подзапросами, что сильно замедляло работу.

– Стало непонятно, на каком этапе и какие фильтры применяются.

– Тестирование разных версий отнимало драгоценное время, и дедлайн был сорван.

Где можно было изменить тактику

Когда началась путаница, выбор был прост: либо продолжать накручивать всё новые условия, либо вернуться к простому базису и более внимательно продумать логику соединений и фильтраций. Потребовался паузу и тщательный разбор, что именно должно соединяться и как.

Ключевые ошибки, которые привели к срыву и которых можно было избежать:

– Неправильный тип джойна. Там, где нужны были только продажи с определёнными клиентами, LEFT JOIN уступает место INNER JOIN – это устраняет избыточные строки с самого начала и упрощает фильтрацию.

– Фильтрация данных после соединения. Перемещение условий из WHERE в ON уменьшают риск дублирования – фильтры в ON работают как условия для соединения, а не постфактум отсекают строки.

– Отсутствие предварительных выборок. Вместо длинных многоуровневых джойнов и подзапросов полезнее сначала выделить отфильтрованные списки клиентов и товаров, а потом соединять их с продажами. Такой подход облегчает понимание и отладку.

Три способа предотвратить повторение ошибок

Чтобы системно улучшить работу с запросами, стоит внедрить несколько принципов.

1. Чёткое структурирование запроса:

Начинайте с основной таблицы, добавляйте джойны последовательно и проверяйте на каждом шаге количество и качество строк. Не забывайте фильтры для каждой таблицы применять в ON, а не в WHERE.

2. Осознанное использование агрегатов и группировок:

Группируйте только по нужным полям. Избыточные колонки в GROUP BY приводят к раздвоению строк, и итоговые суммы искажены. Следите, чтобы поля в SELECT и GROUP BY были согласованы.

3. Предпочтение CTE перед вложенными подзапросами:

Выделяйте промежуточные выборки с помощью WITH – это улучшает читаемость кода и позволяет легко проверять результаты каждого шага без переписывания всего запроса.

Как оставаться в строю, когда сроки давят и запрос не работает

Ошибки – не повод винить себя. Важно понять: работа сложная, и даже профессионалы сталкиваются с такими ситуациями. Вот три мысли, которые помогут не опустить руки:

– «Каждая ошибка – шанс глубже понять структуру данных, а не знак некомпетентности».

– «В сложных запросах всегда есть узкие места, это именно то, на что стоит обратить внимание и сделать лучше».

– «Время и ошибки – часть процесса обучения и экспертизы».

Практика: исправляем ошибочный запрос и шаблон для правильной работы

Рассмотрим простой пример, иллюстрирующий наши правила.

Задача: вывести список клиентов с суммой их покупок за последний месяц, учитывая только товары из конкретной категории.

Неправильный запрос:

SELECT client_id, client_name, SUM(sale_amount)

FROM sales

LEFT JOIN clients ON sales.client_id = clients.id

LEFT JOIN products ON sales.product_id = products.id

WHERE products.category = 'Электроника'

AND sale_date BETWEEN '2024-05-01' AND '2024-05-31'

GROUP BY client_id, client_name

ORDER BY SUM(sale_amount) DESC;

Почему так плохо?

– Использование LEFT JOIN к клиентам и товарам при наличии фильтрации приводит к дублированию строк.

– Фильтрация по категории и дате в WHERE после LEFT JOIN отбросит «лишние» строки, что нарушит логику.

Правильный вариант:

WITH filtered_products AS (

SELECT id FROM products WHERE category = 'Электроника'

),

filtered_clients AS (

SELECT id, client_name FROM clients

)

SELECT c.id AS client_id, c.client_name, SUM(s.sale_amount) AS total_sales

FROM sales s

INNER JOIN filtered_clients c ON s.client_id = c.id

INNER JOIN filtered_products p ON s.product_id = p.id

WHERE s.sale_date BETWEEN '2024-05-01' AND '2024-05-31'