Собесов

CL Медикал: BI-отчёт «Нагрузка по часам» — % заказов по ПЗ

SQLBI-pivotСредняяJunior

Условие

Составить отчёт «Нагрузка по часам»: показать количество заказов по каждому пункту заказа (ПЗ) в час, в процентном выражении.

  • Строки: наименование ПЗ.
  • Столбцы: часы (0–23).
  • Значения: % от общего числа заказов в этом ПЗ.
  • Срезы: направление, населённый пункт, район, признак ковид, год.месяц.
  • Фильтры: статус заказа NOT IN (6, 7), признак ПЗ = 'наши'.

Решение

Подход

Сначала считаем абсолютное количество по (ПЗ, час), потом делим на сумму по ПЗ — получаем долю. В BI это удобно через LOD (Tableau) или меру в DAX (Power BI). На SQL — через оконную функцию.

SQL

WITH base AS (
  SELECT
    pz_name,
    EXTRACT(HOUR FROM order_dttm) AS hour,
    COUNT(*) AS cnt
  FROM orders o
  WHERE o.status NOT IN (6, 7)
    AND o.pz_flag = 'наши'
    -- сюда уйдут срезы (направление, нас.пункт, район, ковид, год-месяц) как фильтры дашборда
  GROUP BY pz_name, EXTRACT(HOUR FROM order_dttm)
),
totals AS (
  SELECT pz_name, SUM(cnt) AS total
  FROM base
  GROUP BY pz_name
)
SELECT
  b.pz_name,
  b.hour,
  100.0 * b.cnt / NULLIF(t.total, 0) AS pct_orders
FROM base b
JOIN totals t ON t.pz_name = b.pz_name
ORDER BY b.pz_name, b.hour;

Tableau LOD

SUM([cnt]) / SUM({FIXED [pz_name] : SUM([cnt])})

Power BI / DAX

PctByPZ :=
DIVIDE(
  COUNTROWS('orders'),
  CALCULATE(COUNTROWS('orders'), ALLSELECTED('orders'[hour]))
)

Подводные камни

  1. Если строка pz_name имеет 0 заказов после фильтра — деление на ноль. NULLIF обязателен.
  2. Срезы пользователь меняет в дашборде — формула должна реагировать. В Tableau {FIXED [pz_name] : ...} правильно реагирует на фильтры контекста; в DAX — ALLSELECTED вместо ALL.
  3. «Часы» — это локальный TZ или UTC? Если данные сырые — конвертировать.
  4. «Год.месяц» как срез — построить отдельное измерение DATE_TRUNC('month', order_dttm).
  5. Сумма по строке должна быть 100% (с округлением).

Эталонный ответ

Двухуровневая агрегация: подсчёт по (ПЗ, час) → деление на сумму по ПЗ. В BI — LOD/ALLSELECTED.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти