6 глав · 18 уроков
Первый урок: Документ в ячейке: объект, массив, значение
Практический курс по JSON в SQL · PostgreSQL, ClickHouse, BigQuery
JSON внутри SQL-таблицы.
От вложенных полей — к метрикам.
Большинство SQL-курсов заканчиваются там, где таблица перестаёт быть прямоугольной. А этот курс там только начинается. На практике в PostgreSQL, ClickHouse и BigQuery научишься извлекать и разворачивать вложенные данные, не терять строки и считать метрики по JSON.
Первая глава бесплатно · остальные 5 глав входят в Pro · Что входит в Pro
- После каждого разворота проверяем, что теперь означает одна строка
- Решения проверяются по результату запроса
- Живые SQL-ячейки в каждом уроке
- Без установки: всё в браузере
CROSS JOIN LATERALjsonb_array_elements(payload->'items') iCROSS JOIN LATERALjsonb_array_elements(payload->'coupons') c
| order | item | coupon |
|---|---|---|
| 5003 | SQL для профи | KOTO10 |
| 5003 | SQL для профи | BOOKS5 |
| 5003 | Чистый код | KOTO10 |
| 5003 | Чистый код | BOOKS5 |
| 5003 | Алгоритмы на практике | KOTO10 |
| 5003 | Алгоритмы на практике | BOOKS5 |
Что болит
Задача с работы и приём для её решения
События приложения, ответы платёжного шлюза, характеристики товаров и настройки — всё в одной колонке jsonb. Под каждой задачей указаны приём из программы и тема главы.
После разворота массива заказов стало меньше
LEFT JOIN LATERALПустой массив и отсутствующий ключ дают ноль строк: заказ исчезает без единой ошибки. В главе о массивах научишься разворачивать их без потери заказов и проверять тип до разворота.
Сумма заказа выросла вдвое после соединения
взрыв строкДва массива в одном документе умножают строки: три товара и два купона дают шесть. Каждый массив нужно агрегировать отдельно, до соединения.
IS NULL находит не те строки
три пустотыКлюча нет. Значение ключа — JSON null. Документа нет, в ячейке SQL NULL. Это три разных состояния с разным смыслом для бизнеса. Курс учит различать их, а не объединять одним COALESCE.
Цена приходит то числом, то строкой, то объектом
типы5990, "1290", "" и {"amount": 3490} в одном поле. Сначала проверь тип через jsonb_typeof, потом приводи к нужному — так запрос не упадёт на первой пустой строке.
После релиза метрика упала, а магазин работает как раньше
дрейф схемыАвтор события теперь указан в actor.id вместо user.id. Старый запрос не падает, а возвращает NULL. В главе о грязных данных ты соберёшь отчёт качества, который замечает такое раньше дашборда.
Запрос из PostgreSQL не работает в ClickHouse и BigQuery
три диалектаВ каждом движке заново решаем одну задачу: считаем сумму товаров по категориям без потери заказов. Используем JSONExtract и arrayJoin, JSON_VALUE и UNNEST, сравниваем JSON и ARRAY<STRUCT>.
Кому подойдёт курс
- Аналитикам, у которых события продукта лежат в колонке payload, а не в аккуратных таблицах
- Инженерам данных и бэкенд-разработчикам, которые хранят в jsonb ответы API, настройки и характеристики
- Тем, кто уверенно пишет SQL, но теряется, когда в ячейке оказывается массив
- Тем, кто работает с ClickHouse или BigQuery и хочет понять разницу между JSON в этих базах и в PostgreSQL
Кому курс не подойдёт
- Тем, кто никогда не писал SELECT и JOIN: основы SQL курс не объясняет
- Тем, кому нужен JSON в JavaScript или Python: курс про SQL и данные в базе
- Тем, кто ищет курс по MongoDB: здесь JSON живёт внутри реляционной базы
Как устроено
Документ — разворот — проверка
В каждом уроке есть живые ячейки, квиз-ловушка и задача «почини запрос». Запрос сразу выполняется на данных. В ловушках SQL написан правильно, но ответ получается неверным.
Что сейчас означает одна строка
После каждого разворота и соединения ты сверяешь COUNT(*) с COUNT(DISTINCT …) по заказу или событию. Эта проверка помогает заметить почти каждую ловушку курса.
Грязные данные, а не идеальный payload
События приложения в трёх версиях схемы, ответы платёжного шлюза в двух версиях API, карточки товаров, настройки покупателей и сырая выгрузка, где попадается не-JSON. Почти каждая строка датасета нужна, чтобы разобрать конкретную ошибку.
Проверка по результату
В задаче «почини запрос» твой SQL выполняется в песочнице, а результат сравнивается с эталоном. Подходит любой запрос, который даёт тот же ответ. В конце каждого урока — две задачи в тренажёре: урок засчитывается, когда решена хотя бы одна.
Девятая смена одной истории
Коробки в коробках
Вместе с базой «Котомаркета» и сырым текстом сигнал принёс на «Хранилище-9» посылки — служебную переписку машин магазина за две недели до обрыва, с 10 по 24 февраля 2025 года. Приложение сообщало о каждом касании, платёжный шлюз отвечал магазину, карточки товаров хранили характеристики, которые не влезли в таблицы. Всё упаковано в фигурные скобки: в таблице это одна колонка, а внутри — целые деревья.
Посылки лежат в Распаковочной, по соседству с Сортировочной. Комендант ждёт сводку за последние две недели работы магазина: что покупали, сколько было заказов, как платили. Наставник тот же — КВЕРИ, старый архивный интеллект с характером кота: «Таблица — это шкаф с полками. JSON — коробка, в которой коробки. Сначала научимся открывать, потом — не терять то, что внутри».
Программа
6 глав, 18 уроков, 9 ч 59 мин
В каждой главе видны уроки и прогресс. Первая глава бесплатна, остальные входят в Pro.
JSON в ячейке
В таблице «Котомаркета» одна колонка, а внутри — целое дерево. Глава учит открывать документ: объект, массив и скаляр, json и jsonb, операторы -> и ->>. И различать три пустоты: ключа нет, JSON null и SQL NULL.
Пути и поиск внутри документа
17 февраля платёжный шлюз сменил формат ответа. Ещё вчера путь работал, а сегодня возвращает NULL. В главе научишься проходить вложенные пути с #> и #>>, искать фрагмент через @> и ? и изучать незнакомый документ, прежде чем писать запрос.
Массивы превращаются в строки
Центральная глава курса. jsonb_array_elements и LATERAL превращают корзину в строки — и тут же ломают отчёт: пустой массив молча съедает заказ, null или строка вместо массива роняют запрос, а два массива в одном документе умножают строки.
Из JSON — в таблицу и обратно
Опись станции принимает только таблицы. jsonb_to_record и jsonb_to_recordset раскладывают документ по полям, jsonb_typeof и pg_input_is_valid проверяют тип до приведения, а jsonb_build_object и jsonb_agg собирают сводку обратно в JSON.
Грязные данные: запрос верный, метрика врёт
После 17 февраля сводка показала, что оформивших заказ стало вдвое меньше, а конверсия упала с 75% до 37,5%. В главе докажем, что сломалась схема событий, а не магазин: разберём три варианта записи автора события, разный смысл пустоты и отчёт качества, который замечает дрейф раньше дашборда.
Три мира: PostgreSQL, ClickHouse, BigQuery
Копии посылок ушли в Читальный зал и Дальний архив. В ClickHouse и BigQuery заново решаем задачу из главы о массивах: считаем сумму товаров по категориям, не теряя заказы. В последнем уроке разбираем, что хранить в JSON, а что выносить в колонки и индексировать.
Границы курса
Чего в курсе нет — и почему
Документные базы: MongoDB и её родня
У них свой язык запросов и своя модель данных. Курс — про JSON внутри реляционной базы, где аналитик встречает его чаще всего.
Зато в последнем уроке ты научишься решать, что хранить в документе, а что выносить в колонки. Это пригодится и в документной базе.
JSON_TABLE и новые функции PostgreSQL 17
В курсе используем PostgreSQL 16: нет смысла учить код, который не запустится в песочнице.
О новых функциях рассказываем в плашках «в новых версиях». Те же задачи решаем средствами PostgreSQL 16: jsonb_to_recordset разбираем в главе 4, jsonpath — на примере из практики в главе 5.
Новый тип JSON в ClickHouse
В курсе используем версию 24.10: в ней этот тип экспериментальный, и его поведение ещё меняется.
Задачу главы решаем с помощью JSONExtract и arrayJoin: они уже работают. О новом типе рассказываем в плашке.
FAQ
Частые вопросы
Да, нужно знать SELECT, WHERE, GROUP BY и JOIN. Всё о JSON курс объясняет с нуля: операторы, функции, разворот массивов и LATERAL.
Посылки ждут распаковки
Первая глава открыта целиком: 3 урока без подписки и карты.