Files
de-roadmap/dwh-modeling/sql/03_validation.sql
T

99 lines
4.3 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- ===============================================
-- Проверки качества данных после загрузки STG→ODS→DDS
-- Запускается после 02_dml.sql
-- ===============================================
-- 1. Проверка: dim_customer не пуста
DO $$
BEGIN
ASSERT (SELECT COUNT(*) FROM dds.dim_customer) > 0,
'ОШИБКА: таблица dds.dim_customer пуста — загрузка не прошла';
RAISE NOTICE '✅ dim_customer: НЕ ПУСТА (всего строк: %)',
(SELECT COUNT(*) FROM dds.dim_customer);
END $$;
-- 2. Проверка: fact_sales содержит все строки из order_items
DO $$
DECLARE
expected_count INT := (SELECT COUNT(*) FROM ods.order_items);
actual_count INT := (SELECT COUNT(*) FROM dds.fact_sales);
BEGIN
ASSERT actual_count = expected_count,
FORMAT('ОШИБКА: в fact_sales %s строк, а в ods.order_items — %s. Разница: %s',
actual_count, expected_count, expected_count - actual_count);
RAISE NOTICE '✅ fact_sales: количество строк совпадает с ods.order_items (%)', actual_count;
END $$;
-- 3. Проверка: у каждого факта есть валидная дата (date_key существует)
DO $$
DECLARE missing_dates INT;
BEGIN
SELECT COUNT(*) INTO missing_dates
FROM dds.fact_sales f
LEFT JOIN dds.dim_date d ON f.date_key = d.date_key
WHERE d.date_key IS NULL;
ASSERT missing_dates = 0,
FORMAT('ОШИБКА: %s фактов ссылаются на несуществующие даты (неверный date_key)', missing_dates);
RAISE NOTICE '✅ Все факты имеют валидные date_key';
END $$;
-- 4. Проверка SCD Type 2: у клиента 101 должно быть ≥2 версий (из-за смены email)
DO $$
DECLARE version_count INT;
BEGIN
SELECT COUNT(*) INTO version_count
FROM dds.dim_customer
WHERE customer_bk = 101;
ASSERT version_count >= 2,
FORMAT('ОШИБКА: у клиента 101 только %s версия, ожидается ≥2 (должна быть история)', version_count);
RAISE NOTICE '✅ SCD Type 2: клиент 101 имеет %s версий — история сохранена', version_count;
END $$;
-- 5. Проверка: сумма amount = qty * price_at_sale (без округления)
DO $$
DECLARE bad_rows INT;
BEGIN
SELECT COUNT(*) INTO bad_rows
FROM (
SELECT
f.sale_id,
f.amount,
oi.qty * oi.price_at_sale AS expected_amount
FROM dds.fact_sales f
JOIN ods.orders o ON f.date_key = CAST(TO_CHAR(o.order_date, 'YYYYMMDD') AS INT)
JOIN ods.order_items oi ON o.order_id = oi.order_id
WHERE ROUND(f.amount, 2) <> ROUND(oi.qty * oi.price_at_sale, 2)
LIMIT 10
) mismatches;
ASSERT bad_rows = 0,
'ОШИБКА: обнаружены расхождения между amount и qty * price_at_sale';
RAISE NOTICE '✅ Все суммы рассчитаны верно (amount = qty × price_at_sale)';
END $$;
-- ===============================================
-- Финальный отчёт для аналитика
-- ===============================================
RAISE NOTICE '──────────────────────────────';
RAISE NOTICE '📊 ОТЧЁТ: Выручка по клиентам (актуальные версии)';
RAISE NOTICE '──────────────────────────────';
SELECT
dc.customer_bk AS "ID клиента",
dc.email AS "Email",
dc.city AS "Город",
SUM(f.quantity) AS "Всего товаров",
SUM(f.amount) AS "Выручка, ₽"
FROM dds.fact_sales f
JOIN dds.dim_customer dc
ON f.customer_sk = dc.customer_sk
AND dc.is_current -- только актуальная версия
GROUP BY dc.customer_bk, dc.email, dc.city
ORDER BY SUM(f.amount) DESC;
RAISE NOTICE '──────────────────────────────';
RAISE NOTICE '✅ Все проверки пройдены. DWH готов к построению витрин.';