Заполнение пропусков в результатах статистических временных рядов

Источник: «Fill Gaps in Statistical Time Series Results»
Статистические расчёты на временном интервале должны учитывать недостающие данные. Вместо того чтобы заполнять недостающие записи в приложении, можно изменить запрос, чтобы делать это напрямую.

Результаты некоторых статистических расчётов будут иметь пропуски, поскольку информация за конкретные дни не сохранялась. Но вместо того, чтобы заполнять эти пустоты кодом приложения, можно перестроить запрос к базе данных: В качестве источника для присоединения к статистическим данным создаётся последовательность значений без пропусков. Для PostgreSQL для создания последовательности можно использовать функцию generate_series, в то время как для MySQL это необходимо делать вручную с помощью рекурсивного общего табличного выражения (CTE).

Использование

MySQL

WITH RECURSIVE dates_without_gaps(day) AS (
SELECT DATE_SUB(CURRENT_DATE, INTERVAL 14 DAY) as day
UNION ALL
SELECT DATE_ADD(day, INTERVAL 1 DAY) as day
FROM dates_without_gaps
WHERE day < CURRENT_DATE
)
SELECT dates_without_gaps.day, COALESCE(SUM(statistics.count), 0)
FROM dates_without_gaps
LEFT JOIN statistics ON(statistics.day = dates_without_gaps.day)
GROUP BY dates_without_gaps.day;

PostgreSQL

SELECT dates_without_gaps.day, COALESCE(SUM(statistics.count), 0)
FROM generate_series(
CURRENT_DATE - INTERVAL '14 days',
CURRENT_DATE,
'1 day'
) as dates_without_gaps(day)
LEFT JOIN statistics ON(statistics.day = dates_without_gaps.day)
GROUP BY dates_without_gaps.day;

Подробное объяснение

Многие приложения содержат статистически интересную информацию, такую как регистрация пользователей, количество созданных статей в блоге или продаж. Для целей отчётности эти ряды часто обобщаются по определённым временным интервалам, таким как дни, недели или месяцы. В результате получается временной ряд, показывающий изменение значений за равные промежутки времени. Однако во временном ряду отсутствуют некоторые значения, когда в одном или нескольких периодах не было никаких событий. Если эти данные отобразить на графике, то график будет вводить в заблуждение, поскольку, например, за январём будет непосредственно следовать апрель.

Разрывы в данных традиционно устраняются в приложении. Но при этом увеличивается объем многословного кода, поскольку обработка временных интервалов должна быть скопирована из базы данных, иногда с дополнительными сложностями, связанными с настраиваемыми пользователем временными интервалами и периодами. Программисту приходится разрабатывать две различные реализации статистического обобщения: одну для построения запроса и вторую для заполнения пропусков. Наиболее простым решением было бы создание одного SQL-запроса, выдающего результаты без разрывов.

Идея заключается в том, чтобы изменить рабочий процесс, заполнив разрывы до вычисления статистики. Создаётся отношение с именем dates_without_gaps, которое содержит все даты, доступные после расчёта, если бы данные не содержали пропущенных значений. С помощью этого отношения статистические данные могут быть соединены со ссылкой на временной интервал, так что в результате не будет никаких пропусков, если в некоторые дни не было данных. Построение этого временного отношения не представляет сложности при работе с PostgreSQL: Функция generate_series создаёт все данные на основе интервала и начальной вместе с конечной точкой. В то время как для MySQL это необходимо делать вручную, используя рекурсивное общее табличное выражение (CTE).

Дополнительные ресурсы

Дополнительные материалы

Предыдущая Статья

Ограничение области действия селекторов с помощью CSS правила @scope

Следующая Статья

Понять Композицию в JavaScript раз и навсегда