Уточнения по SCD 2 - бех юэкфилл

This commit is contained in:
2025-11-07 15:46:52 +03:00
parent b29de24c31
commit 57d1dd3186
3 changed files with 19 additions and 15 deletions
+5 -1
View File
@@ -14,13 +14,15 @@ CREATE SCHEMA ods;
CREATE SCHEMA dds;
-- 2. STG: сырые данные (как пришли)
DROP TABLE IF EXISTS stg.customers_raw;
CREATE TABLE stg.customers_raw (
customer_id TEXT, -- может быть строкой или числом
email TEXT,
phone TEXT,
city TEXT,
event_ts TEXT,
_load_id TEXT, -- идентификатор загрузки (обязательно!)
_load_ts TIMESTAMP DEFAULT NOW(), -- время получения в DWH
_load_ts TIMESTAMP DEFAULT NOW() -- время получения в DWH
);
CREATE TABLE stg.orders_raw (
@@ -43,11 +45,13 @@ CREATE TABLE stg.products_raw (
);
-- 3. ODS: очищенные данные
DROP TABLE IF EXISTS ods.customers;
CREATE TABLE ods.customers (
customer_id INT NOT NULL, -- привели к INT
email VARCHAR(100),
phone VARCHAR(20),
city VARCHAR(50),
event_ts TIMESTAMP,
_load_id TEXT NOT NULL, -- сохраняем для отладки и SCD
_load_ts TIMESTAMP NOT NULL -- время загрузки (копия из STG)
);
+9 -9
View File
@@ -37,12 +37,13 @@ INSERT INTO stg.products_raw (product_id, name) VALUES
TRUNCATE ods.customers, ods.orders, ods.order_items, ods.products;
INSERT INTO ods.customers (customer_id, email, phone, city)
INSERT INTO ods.customers (customer_id, email, phone, city, event_ts, _load_id, _load_ts)
SELECT
customer_id::INT,
NULLIF(TRIM(email), ''),
NULLIF(TRIM(phone), ''),
NULLIF(TRIM(city), ''),
event_ts::timestamp,
_load_id,
_load_ts
FROM stg.customers_raw
@@ -81,7 +82,7 @@ DELETE FROM dds.dim_date;
WITH RECURSIVE dates AS (
SELECT DATE '2023-01-01' AS d
UNION ALL
SELECT d + INTERVAL '1 day'
SELECT (d + INTERVAL '1 day')::DATE -- ← приведение к DATE
FROM dates
WHERE d + INTERVAL '1 day' <= DATE '2027-12-31'
)
@@ -96,7 +97,7 @@ SELECT
EXTRACT(QUARTER FROM d)::SMALLINT,
EXTRACT(MONTH FROM d)::SMALLINT,
EXTRACT(DAY FROM d)::SMALLINT,
TO_CHAR(d, 'Day'),
TRIM(TO_CHAR(d, 'Day')), -- ← TRIM — убрать trailing space
EXTRACT(DOW FROM d)::SMALLINT,
d BETWEEN DATE_TRUNC('month', d)
AND DATE_TRUNC('month', d) + INTERVAL '1 month' - INTERVAL '1 day'
@@ -130,8 +131,7 @@ BEGIN;
PARTITION BY s.customer_id
ORDER BY COALESCE(s.event_ts, s._load_ts) DESC, s._load_ts DESC
) AS rn
FROM stg.customers_raw s
WHERE s.customer_id ~ '^\d+$'
FROM ods.customers s
),
delta AS (
-- берём по BK последнюю версию из поступивших данных
@@ -192,11 +192,11 @@ SELECT
oi.price_at_sale * oi.qty
FROM ods.orders o
JOIN ods.order_items oi ON o.order_id = oi.order_id
JOIN ods.products p ON oi.product_id = p.product_id
JOIN ods.products p ON oi.product_id = p.product_id
JOIN dds.dim_product dp ON p.product_id = dp.product_bk
JOIN dds.dim_customer dc
ON o.customer_id = dc.customer_bk
AND o.order_date BETWEEN dc.valid_from AND dc.valid_to;
JOIN dds.dim_customer dc
ON o.customer_id = dc.customer_bk
AND o.order_date::timestamp BETWEEN dc.valid_from AND dc.valid_to;
-- 7. Проверка — вывод итогов (не часть ETL, но полезно для отладки)
-- В реальном пайплайне такие SELECT выносятся в отдельные скрипты или дашборды