Модуль 9 · Урок 35
JOIN, aggregation і reconciliation
Сильний data oracle пояснює cardinality: чому після JOIN саме стільки rows, що рахує aggregate і чи збігаються detail, grouped totals та source-of-truth.
Спочатку визначте grain
Grain — що означає один row у result: один member, loan, book чи member×book. Перед JOIN запишіть expected relationship 1:1, 1:N або N:M. One-to-many закономірно множить parent rows; помилковий/відсутній ON condition може створити Cartesian explosion.
| JOIN | QA застосування |
|---|---|
| INNER JOIN | Лише matched rows; missing relationship зникає з result. |
| LEFT JOIN | Усі rows ліворуч плюс matches; unmatched right columns стають NULL. |
| Anti-join | `LEFT JOIN … WHERE right.key IS NULL` знаходить missing relationship. |
| Self-join | Порівняння rows однієї table; aliases обов’язково пояснюють roles. |
ON і WHERE змінюють outer join
Condition на right table у `WHERE` часто відкидає NULL unmatched rows і фактично перетворює LEFT JOIN на inner-like result. Якщо condition описує matching rule, тримайте його в `ON`; якщо filter потрібен після JOIN — явно зафіксуйте expected loss.
COUNT теж має semantics
`COUNT(*)` рахує result rows, `COUNT(column)` — лише non-NULL values, `COUNT(DISTINCT key)` — distinct non-NULL keys. Вибір має відповідати grain та requirement.
GROUP BY, HAVING і control totals
WHERE filters rows до grouping; HAVING filters groups після aggregation. Для duplicates використовуйте key columns + `HAVING COUNT(*) > 1`. Для reconciliation порівнюйте detail count/sum із незалежним grouped/control total, однаковим scope, timezone, status rules і rounding policy.
Практика
У `reconciliation-matrix.csv` перевірте open-loan detail проти grouping за member, знайдіть book без loan і доведіть відсутність duplicate email. Додайте одну навмисно неправильну JOIN-умову в нотатках, не в production query.
Офіційні джерела
Закріпіть матеріал уроку
Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.