TGViewer
Дмитрий Кузьмин | Инженерия данных Дмитрий Кузьмин | Инженерия данных @kuzmin_dmitry91 · 1.75K subscribers
Post #260 815
💬 Какой результат SQL отправить бизнесу?

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

Покажу на небольшом примере.

Менеджер присылает таблицу с заказами за сентябрь и просит посчитать, сколько клиентов было за месяц. Вроде бы обычная задача на COUNT, которую можно закрыть одним запросом.

order_id | customer_id | order_date
---------+-------------+-----------
1001 | 1 | 2026-09-02
1002 | 1 | 2026-09-11
1003 | 2 | 2026-09-04
1004 | 3 | 2026-09-06
1005 | 3 | 2026-09-18
1006 | 4 | 2026-09-22


На первый взгляд задача простая, но по этим данным можно вернуть как минимум три правдоподобных ответа: 6, 4 или 2. Какой из них вы бы отправили менеджеру?

Попробуйте сначала выбрать свой вариант, а затем посмотреть разбор ниже.

Теперь разбираемся

Если выполнить COUNT(*), получится 6, но это количество заказов, поскольку одна строка в таблице соответствует одному заказу. Запрос выполнился правильно, только на вопрос о клиентах он не ответил.

COUNT(DISTINCT customer_id) вернёт 4. Это количество уникальных клиентов, которые сделали хотя бы один заказ в сентябре, и именно такой смысл чаще всего подразумевают под числом покупателей за период.

Если сгруппировать данные по customer_id и оставить клиентов с двумя и более заказами, получится 2. Но называть их повторными клиентами пока рано: мы видим только сентябрь и не знаем, покупали ли клиенты 2 и 4 раньше. Для одного бизнеса повторная покупка означает второй заказ внутри месяца, а для другого любой заказ после первой покупки за всё время.

Все три числа можно получить корректным SQL-запросом:

with customer_orders as (
select
customer_id,
count(*) as orders_cnt
from orders
where order_date >= '2026-09-01'
and order_date < '2026-10-01'
group by customer_id
)
select
sum(orders_cnt) as orders_cnt,
count(*) as buyers_cnt,
sum(
case
when orders_cnt >= 2 then 1
else 0
end
) as clients_with_2plus_orders
from customer_orders;


Обратите внимание на границу периода: условие order_date < '2026-10-01' безопаснее, чем попытка перечислить все возможные значения последнего дня сентября, особенно если в поле хранится не только дата, но и время.

Результат будет таким:

orders_cnt | buyers_cnt | clients_with_2plus_orders
-----------+------------+--------------------------
6 | 4 | 2


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

Уточню смысл: считаем всех уникальных покупателей с заказом в сентябре, клиентов с двумя и более заказами внутри месяца или тех, кто в сентябре вернулся после своей первой покупки за всю историю?


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

Поэтому я бы не отправлял ни 6, ни 4, ни 2, пока не зафиксирован смысл метрики. Хороший запрос начинается с ответа на два вопроса: что означает одна строка исходных данных и какой бизнес-смысл должна иметь итоговая цифра.

❔ Если хотите проверить, где у вас заканчивается уверенный SQL, на сайте есть страница с небольшой диагностикой.

#материалы
kuzmin-dmitry.ru Практические курсы SQL для работы и собеседований Курсы SQL с практическими задачами: от SELECT, JOIN и GROUP BY до CTE, оконных функций и собеседований уровня Middle. Выберите подходящий маршрут.
  • 🔥 10
  • 👍 8
  • ❤ 1
More from @kuzmin_dmitry91
  1. Sep 28, 2026⚙️ Инженер данных: системные знания для профессионального роста 5 октября на Факультете ко…
  2. Sep 25, 2026Можно отдельно изучить SQL, Spark и Airflow, а потом всё равно не понимать, как связать их…
  3. Sep 22, 2026Почему RAG-бот иногда отвечает «не знаю» ✍️ В августе я только начинал погружаться в RAG и…
  4. Sep 18, 2026У блога появился свой герой 🐻 В последнее время здесь много пайплайнов, проверок качества…
  5. Sep 11, 2026Когда пайплайн упал в пятницу в 18:30, но дежуришь не ты. С пятницей! Пусть выходные пройд…
  6. Sep 10, 2026Сначала выучу весь DE-стек У меня переход в Data Engineering тормозился примерно на этой м…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →