Data Analyst Professional · Модуль 4 · Урок 12 із 51
Ключі й безпечний JOIN без множення фактів
JOIN з’єднує рядки за умовою, але не знає вашого expected grain. Якщо праворуч кілька відповідностей, факти зліва повторяться. Тому до синтаксису потрібні cardinality contract, перевірка ключів і reconciliation після кожного з’єднання.
Почніть із cardinality contract
| Зв’язок | Приклад | Що стається з рядками | Основний ризик |
|---|---|---|---|
| one-to-one | order → approved_order_profile | 0 або 1 match | неочікувані дублікати ключа праворуч |
| many-to-one | orders → customers | кожне order має максимум 1 customer | неунікальний customer_id у dimension |
| one-to-many | orders → order_items | order повторюється для кожної позиції | double counting order-level amount |
| many-to-many | campaigns ↔ tags | комбінації множаться | вибух рядків без bridge/aggregation rule |
INNER і LEFT JOIN відповідають на різні питання
-- Лише замовлення з наявним клієнтом
SELECT o.order_id, c.segment
FROM analytics.orders AS o
INNER JOIN analytics.customers AS c
ON c.customer_id = o.customer_id;-- Усі замовлення, навіть якщо профіль клієнта відсутній
SELECT o.order_id, c.segment
FROM analytics.orders AS o
LEFT JOIN analytics.customers AS c
ON c.customer_id = o.customer_id;Для LEFT JOIN unmatched поля праворуч стають NULL. Якщо після цього фільтрувати WHERE c.segment = 'B2B', unmatched rows зникнуть, і поведінка наблизиться до INNER JOIN. Умову треба розміщувати відповідно до business intent.
Перевірки до JOIN
Скільки rows і distinct expected key має базова вибірка?
Чи унікальний join key праворуч, якщо очікується many-to-one?
Скільки NULL та порожніх ключів з обох боків?
Скільки left keys matched, unmatched і matched multiple times?
SELECT customer_id, COUNT(*) AS rows_per_key
FROM analytics.customers
GROUP BY customer_id
HAVING COUNT(*) > 1;Fan-out: найнебезпечніша тиха помилка
Якщо сума orders.net_amount зберігається на grain order, після JOIN з order_items вона повториться на кожній позиції. SUM(o.net_amount) завищить виручку.
SUM(DISTINCT net_amount): однакові суми різних orders будуть помилково схлопнуті.Reconciliation після JOIN
| Контроль | До | Після | Інтерпретація |
|---|---|---|---|
| row count | 10 000 orders | 12 840 rows | є one-to-many або duplicate matches |
| distinct order_id | 10 000 | 9 980 | 20 orders втрачено через INNER JOIN/filter |
| unmatched | — | 73 | quality issue або очікувана відсутність dimension |
| control total | ₴5,2 млн | ₴6,8 млн | факт повторився; висновок заборонений |
Практика: join audit
- Запишіть grain і expected cardinality обох таблиць.
- Перевірте дублікати та NULL join key праворуч.
- Виконайте LEFT JOIN і позначте matched/unmatched.
- Звірте rows, distinct left key і контрольний total до/після.
- Якщо є fan-out, pre-aggregate праву таблицю або розділіть KPI за grain.
Офіційні довідки
Готовність до тесту
Ви можете передбачити cardinality, відрізнити INNER від LEFT JOIN, знайти fan-out і довести коректність через row/key/total reconciliation.
Закріпіть матеріал уроку
Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.