Модели «Гонца» разложены по слоям, и Отто просит новую витрину: сколько заказов в каждой зоне доставлено и сколько отменено. На каждый статус по колонке. Пишешь первую строку count(*) filter (where status = 'delivered') as delivered_orders, копируешь, меняешь слово. Для двух статусов терпимо. А завтра у «Гонца» появятся статусы «возвращён» и «потерян», и каждую копию придётся найти и дописать во всех витринах. Повторяющийся SQL хочется не писать, а генерировать.
Бланк письма
В бухгалтерии есть бланк: «Уважаемый ___, напоминаем, что за ___ у вас задолженность ___ рублей». Бланк один, а писем сотни: в пропуски подставляют имя, месяц и сумму. Никто не перепечатывает письмо целиком для каждого клиента.
Модель dbt тоже бланк. Ты пишешь SQL с пропусками и правилами, а dbt перед запуском заполняет пропуски и отдаёт базе готовый запрос.
Что такое Jinja
Jinja это шаблонизатор, язык таких бланков. Ты им уже пользовался: {{ ref('stg_orders') }} и {% if is_incremental() %} это Jinja. Перед запуском dbt компилирует модель: исполняет всё в фигурных скобках и оставляет чистый SQL. База Jinja никогда не видит.
Скобок три вида:
{{ ... }}вставляет значение в текст: имя таблицы, число, строку;{% ... %}это команда: условие, цикл, переменная. Сама по себе в текст ничего не печатает;{# ... #}комментарий шаблона, в скомпилированный SQL он не попадёт.
Переменные и циклы
Переменную заводят командой set:
{% set statuses = ['delivered', 'cancelled'] %}
Квадратные скобки это список, как в Python. По списку можно пройти циклом for, и текст внутри повторится для каждого элемента:
select
zone_id,
{% for status in statuses %}
count(*) filter (where status = '{{ status }}') as {{ status }}_orders{{ "," if not loop.last }}
{% endfor %}
from {{ ref('stg_orders') }}
group by zone_id
На каждом шаге вместо {{ status }} подставляется очередной статус: и внутри кавычек, и в имени колонки.
Отдельная забота: запятые. Между колонками запятая нужна, а после последней SQL её не простит. Внутри цикла есть служебная переменная loop, и loop.last истинно на последнем шаге. Выражение {{ "," if not loop.last }} печатает запятую везде, кроме последней строки.
Появится новый статус, ты допишешь его в список, и колонка возникнет сама.
урок из курса
Урок из курса «Data Engineering». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.