11 KiB
Домашка: статусы клиента от STG до DDS (и немного DM)
Небольшое практическое задание на 1–2 вечера: по данным о смене статусов клиента (CRM) построить цепочку слоёв STG → ODS → DDS (SCD2) и, по желанию, небольшую витрину в dm.
Цель — потренировать руками:
- работу со слоями DWH (stg / ods / dds / dm);
- проектирование и загрузку измерения с историей (SCD Type 2);
- аккуратную работу со временем (
event_ts,valid_from,valid_to).
Исходим из того, что вы уже прошли основную статью dwh-modeling/README.md и познакомились с примером интернет‑магазина.
1. Данные: события смены статуса клиента
Представьте, что в CRM для каждого клиента хранится история статусов:
new— только что зарегистрировался;active— делал покупки недавно;vip— часто покупает и много тратит;churned— давно ничего не делал, считаем «отвалившимся».
Эта информация приходит в DWH в виде событий (events): «у клиента X в момент времени Y статус стал Z».
В репозитории в каталоге dwh-modeling/data лежит файл:
customer_status_events.csv
Структура файла:
customer_id,status,event_ts,_load_id,load_ts
101,new,2024-01-01 09:00:00,batch_20250405_0800,2025-04-05 08:00:00
...
Колонки:
customer_id— бизнес-ключ клиента (тот же, что и в основном примере — 101, 102, 103);status— статус клиента в CRM (new,active,vip,churned);event_ts— момент, когда статус сменился в CRM;_load_id— идентификатор батча загрузки;load_ts— момент, когда данные попали в DWH.
Файл содержит несколько клиентов и несколько смен статуса по каждому — этого достаточно, чтобы отработать SCD2.
2. Целевая схема: какие таблицы уже есть
Чтобы не тратить время на DDL, структуры таблиц для домашки уже подготовлены в dwh-modeling/sql:
07_ddl_hw_customer_status.sql— создаёт дополнительные таблицы:stg.customer_status_raw— сырые события о статусе клиента;ods.customer_status— очищенные и типизированные события;dds.dim_customer_status— измерение статусов клиента в формате SCD Type 2.
08_dml_hw_customer_status_template.sql— шаблон DML-скрипта с подсказками и заготовками блоков.
Перед началом работы:
- Поднимите demo‑Postgres по инструкции из корневого
README.md. - Выполните базовые скрипты DWH:
01_ddl_stg-dds.sql02_dml_stg-dds.sql
- Выполните DDL для домашки:
07_ddl_hw_customer_status.sql
После этого схемы stg, ods, dds уже существуют, а дополнительные таблицы для статусов созданы.
3. Часть 1 — STG → ODS (обязательно)
Задача: загрузить CSV в STG и переложить данные в ODS с приведением типов.
3.1. STG: загрузка CSV
- Откройте
psqlв контейнере (см. инструкцию вpostgres-bookings/README.md). - Загрузите файл
customer_status_events.csvв таблицуstg.customer_status_raw:- можно использовать
\copyизpsql; - либо любой другой способ, к которому вы привыкли.
- можно использовать
- Убедитесь, что данные загрузились:
SELECT * FROM stg.customer_status_raw LIMIT 10;
3.2. ODS: очистка и типизация
В файле 08_dml_hw_customer_status_template.sql найдите заготовку блока ODS и допишите SQL:
- привести:
customer_id→INT,status→VARCHAR(20)(можно оставить как есть),event_tsиload_ts→TIMESTAMP;
- аккуратно обработать возможные пустые значения (если бы они были);
- заполнить
_load_idи_load_tsвods.customer_status.
Проверьте, что в ods.customer_status данные выглядят аккуратно:
SELECT *
FROM ods.customer_status
ORDER BY customer_id, event_ts;
4. Часть 2 — ODS → DDS (SCD Type 2, обязательно)
Задача: по событиям в ods.customer_status построить измерение dds.dim_customer_status, где каждая строка — период действия статуса.
Целевая таблица уже создана (см. 07_ddl_hw_customer_status.sql):
customer_bk— бизнес-ключ клиента (тот же, чтоcustomer_idв ODS);status— статус клиента;hashdiff— хэш от атрибутов (здесь достаточно самогоstatus);valid_from/valid_to— период, когда статус был актуален;is_current— флаг актуальной строки;created_at/updated_at— технические поля.
4.1. Начальная загрузка SCD2
В шаблоне 08_dml_hw_customer_status_template.sql допишите блок начальной загрузки:
-
Сформируйте промежуточный набор:
customer_bk,status,event_ts(как «время начала действия статуса»),hashdiff(например,md5(status)илиdds.customer_hash(status)по аналогии сdim_customer).
-
Для каждого клиента отсортируйте события по
event_tsи с помощьюLEAD()посчитайте:valid_from— текущееevent_ts,valid_to— следующееevent_ts - 1 second(или9999-12-31, если следующего нет).
-
Вставьте получившиеся строки в
dds.dim_customer_status:
INSERT INTO dds.dim_customer_status (
customer_bk, status, hashdiff,
valid_from, valid_to,
is_current, created_at, updated_at
)
SELECT
...
Проверьте результат:
SELECT *
FROM dds.dim_customer_status
ORDER BY customer_bk, valid_from;
Ожидаемое поведение:
- у клиента 101 несколько строк с разными статусами и непересекающимися периодами;
is_current = TRUEтолько у самой свежей строки для каждого клиента.
4.2. Проверка себя
Примеры проверочных запросов (можно придумать свои):
- «Какой статус был у клиента 101 на дату
2024-06-01?»
→ одна строка с нужным статусом. - «Сколько клиентов были в статусе
activeна2024-04-10?»
→ несколько строк, если статус активен для диапазона дат.
5. Часть 3 — инкрементальная загрузка (по желанию)
Если хочется потренироваться глубже:
- Добавьте в CSV ещё несколько событий смены статуса (например, переход части клиентов из
churnedобратно вactive). - Загрузите новые строки только в
stg.customer_status_raw. - Напишите логику инкрементального обновления
dds.dim_customer_status:
- ориентируйтесь на пример из
03_demo_increment.sqlдляdds.dim_customer; - важно:
- корректно «закрыть» старую актуальную строку (
valid_to,is_current = FALSE); - вставить новую строку с
is_current = TRUE.
- корректно «закрыть» старую актуальную строку (
Эта часть особенно полезна, если вы хотите почувствовать, как SCD2 живёт в реальном DWH.
6. Часть 4 — витрина в DM (по желанию)
Опциональное задание для закрепления: собрать небольшую витрину с количеством клиентов по статусам на каждую дату.
Пример целевой таблицы:
CREATE TABLE dm.mart_customer_status_daily (
date_actual DATE NOT NULL,
status VARCHAR(20) NOT NULL,
customers_cnt INT NOT NULL
);
Идея:
- использовать
dds.dim_dateкак календарь; - для каждой
date_actualнайти, какой статус был у клиента в этот день (черезJOINнаdds.dim_customer_statusпо диапазонуvalid_from/valid_to); - агрегировать по
status.
Пример запроса к витрине:
SELECT
date_actual,
status,
customers_cnt
FROM dm.mart_customer_status_daily
WHERE date_actual BETWEEN '2024-04-01' AND '2024-04-30'
ORDER BY date_actual, status;
7. Как вписать эту домашку в обучение
Рекомендуемое место в дорожке:
- Пройти основную теорию по DWH и SCD:
dwh-modeling/README.mddwh-modeling/SCD.md
- Разобрать базовый пример интернет‑магазина (скрипты
01_–06_). - Выполнить эту домашку как первую попытку «самостоятельного» моделирования и ETL:
- познакомиться с ещё одним измерением с историей (
dim_customer_status); - потренироваться аккуратно работать с датами и периодами;
- при желании — собрать простую витрину в
dm.
- познакомиться с ещё одним измерением с историей (
Если что‑то не получается — можно разбирать решения по шагам вместе с ментором: от простого SELECT из STG до полноценного SCD2 в DDS.