Раздел 42 · Аналитика данных с нуля

Стайлгайд SQL: оформление, имена и ревью чужого запроса

middle~20 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Бран · продюсер MMORPG «Хроники Пограничья»

Прошлый подрядчик оставил отчёт по каналам привлечения. По нему органика приносит 434 тысячи, а реклама копейки. Я уже собрался резать рекламный бюджет. Посмотрите запрос, ему можно верить?

Вот что оставил подрядчик, слово в слово:

select a.channel,count(distinct a.id) players,count(distinct b.player_id) payers,sum(b.amount_rub) revenue
from players a left join purchases b on a.id=b.player_id left join characters c on a.id=c.player_id
where b.status='paid' or b.status is null and a.email not like '%@studio.dev'
group by 1 order by 4 desc
  channel   | players | payers |  revenue
------------+---------+--------+-----------
 organic    |    1563 |    219 | 434134.00
 ads_vk     |     804 |    102 | 152527.00
 crosspromo |     418 |     62 | 147893.00
 ads_yandex |     587 |     68 |  56127.00
 bloggers   |     712 |     55 |  53076.00

Запрос выполняется, цифры правдоподобные. В сумме 843 757 ₽. А из проекта про экономику Пограничья мы знаем чистую выручку игры: 657 756 ₽. Откуда-то взялись лишние 186 тысяч, и в четырёх строках не видно откуда. Сегодня учимся писать так, чтобы такие ошибки было видно, и читать чужие запросы так, чтобы их находить.

Столбик цифр в тетради

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

Стайлгайд SQL работает так же. Каждое условие на своей строке, каждый столбец на своей строке, каждый шаг расчёта под своим именем. Тогда «OR посреди столбика AND» и «DISTINCT там, где строк должно быть по одной» бросаются в глаза.

Стайлгайд «Северного Тракта»

Агентство договорилось о десяти правилах. Первые шесть про то, как запрос выглядит, последние четыре про ловушки, которые оформление помогает поймать.

  1. Ключевые слова заглавными, имена строчными. SELECT, FROM, LEFT JOIN, а функции и столбцы как в курсе: count(*), amount_rub.
  2. Один столбец на строку, части запроса с новой строки: SELECT, FROM, каждый JOIN, WHERE, GROUP BY. Условия WHERE и ON тоже по одному на строку, AND в начале строки.
  3. Осмысленные псевдонимы. pl для players, rev для выручки на игрока. Не a, b, c по порядку появления: на десятой строке уже не вспомнить, что такое b.
  4. Явный JOIN ... ON, никогда таблицы через запятую с условиями в WHERE. Условие соединения стоит рядом с таблицей, и его не перепутать с фильтром.
  5. GROUP BY и ORDER BY по именам, а не по номерам. GROUP BY 1 ломается молча, когда кто-то переставит столбцы.
  6. CTE с говорящими именами вместо матрёшки подзапросов, как в уроке про CTE. Комментарий объясняет «зачем», а не «что»: -- эхо вебхука: тот же чек второй строкой, а не -- фильтр по id.
  7. OR внутри WHERE всегда в скобках. AND связывает сильнее OR, и без скобок условие читается не так, как задумано. Для одного столбца лучше IN (…).
  8. Не NOT IN с подзапросом, а NOT EXISTS. Один NULL в подзапросе превращает ответ в пустоту, это мина из урока про подзапросы.
  9. Фильтр по правой таблице LEFT JOIN ставим в ON, а не в WHERE. Иначе строки без пары молча выпадают, как в уроке про LEFT JOIN.
  10. COUNT(DISTINCT …) это запах. Сам по себе он не ошибка, но спроси, почему строки повторяются. Если причина в соединении двух «многих» сторон, то sum в том же запросе посчитан по размноженным строкам.

урок из курса

Урок из курса «Аналитика данных с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.