Data Analyst Professional · Модуль 4 · Урок 13 із 51

GROUP BY та агрегатні функції: правильний grain результату

Агрегація стискає багато source rows до одного рядка на кожну групу. Професійний запит явно визначає grouping grain, розрізняє COUNT(*), COUNT(field) і COUNT(DISTINCT key), а rates рахує як ratio of sums.

90–120 хвAggregation grainМінітест: 3 питання

GROUP BY змінює grain

SELECT country_code, DATE_TRUNC('month', order_ts) AS order_month, COUNT(*) AS order_row_count, COUNT(DISTINCT order_id) AS unique_orders, SUM(net_amount) AS net_revenue FROM analytics.orders WHERE status = 'completed' GROUP BY country_code, DATE_TRUNC('month', order_ts);

Результат має grain country × month. Кожна неагрегована колонка SELECT повинна бути частиною GROUP BY або функціонально визначатися нею відповідно до правил СУБД.

COUNT має три різні сенси

ВиразЩо рахуєNULLТипове застосування
COUNT(*)рядки групивключає рядокrow count на source grain
COUNT(email)non-NULL emailпропускає NULLзаповнені значення
COUNT(DISTINCT customer_id)унікальні non-NULL customer IDsNULL не рахуєтьсяunique customers

Називайте одиницю

count — слабкий alias. Використовуйте order_row_count, customers_with_email або unique_customers.

NULL в SUM і AVG

Більшість агрегатних функцій ігнорує NULL. Якщо всі значення групи NULL, SUM може повернути NULL, а не zero. COALESCE(SUM(amount),0) допустимий лише коли бізнес справді трактує відсутність фактів як нульову суму.

SUMПідсумовує non-NULL values; перевіряйте currency і sign.
AVGСереднє non-NULL rows; denominator може змінюватися через missing.
MIN/MAXКорисні для range QA, але не доводять повну якість distribution.
DISTINCTЗмінює множину values; не є універсальним засобом від fan-out.

WHERE фільтрує rows, HAVING — groups

SELECT customer_id, SUM(net_amount) AS revenue FROM analytics.orders WHERE status = 'completed' -- до aggregation GROUP BY customer_id HAVING SUM(net_amount) >= 10000; -- після aggregation

У WHERE не можна посилатися на результат агрегату того самого рівня. HAVING відбирає вже сформовані groups; не переносіть туди звичайний row filter без причини.

Rate: ratio of sums, не average of row rates

SELECT channel, SUM(conversions) AS conversions, SUM(sessions) AS sessions, SUM(conversions)::numeric / NULLIF(SUM(sessions), 0) AS conversion_rate FROM analytics.daily_channel GROUP BY channel;

Середнє денних rates надає малому й великому дню однакову вагу. Ratio of sums використовує фактичний denominator. NULLIF(...,0) явно захищає division by zero.

Практика: metric reconciliation

  • Запишіть source grain і output grouping grain.
  • Порівняйте COUNT(*), COUNT(key), COUNT(DISTINCT key).
  • Порахуйте NULL у measure і поясніть denominator AVG.
  • Застосуйте WHERE до row scope і HAVING до aggregate threshold.
  • Звірте sum groups із control total без grouping.

Офіційні довідки

Готовність до тесту

Ви називаєте grain group result, розрізняєте види COUNT, знаєте NULL semantics, використовуєте HAVING за призначенням і рахуєте weighted rate через ratio of sums.

Практична перевірка · урок 13 з 51

Закріпіть матеріал уроку

Три сценарні питання. Для зарахування уроку потрібно дати щонайменше дві правильні відповіді.

1. Що визначає GROUP BY?
2. Що рахує COUNT(*)?
3. Що рахує COUNT(email)?