Обратная засыпка пропущенных данных по временной серии без использования <= join? - PullRequest
0 голосов
/ 13 июня 2019

У меня есть таблица, которая примерно соответствует этой схеме:

Table Name: history
╔════╤══════╤══════════╤═════╤═════════════════════╗
║ id │ stat │ stat_two │ ... │ updated_at          ║
╠════╪══════╪══════════╪═════╪═════════════════════╣
║ 1  │ 100  │ 5        │ ... │ 2019-01-01 12:30 PM ║
╟────┼──────┼──────────┼─────┼─────────────────────╢
║ 1  │ 105  │ 7        │ ... │ 2019-01-02 12:30 PM ║
╟────┼──────┼──────────┼─────┼─────────────────────╢
║ 1  │ 300  │ 10       │ ... │ 2019-02-01 12:30 PM ║
╟────┼──────┼──────────┼─────┼─────────────────────╢
║ 1  │ 700  │ 20       │ ... │ 2019-05-01 12:30 PM ║
╟────┼──────┼──────────┼─────┼─────────────────────╢
║ 2  │ 50   │ 0        │ ... │ 2019-01-01 12:30 PM ║
╟────┼──────┼──────────┼─────┼─────────────────────╢
║ 2  │ 55   │ 0        │ ... │ 2019-01-02 12:30 PM ║
╟────┼──────┼──────────┼─────┼─────────────────────╢
║ 2  │ 75   │ 3        │ ... │ 2019-02-01 12:30 PM ║
╟────┼──────┼──────────┼─────┼─────────────────────╢
║ 2  │ 90   │ 7        │ ... │ 2019-05-01 12:30 PM ║
╚════╧══════╧══════════╧═════╧═════════════════════╝

Таблица очень большая.

Я пытаюсь получить следующий результат, хотя фильтрация включает только некоторые IDS (например, только 1 и 2):

╔═════════╤═══════════════════╤═══════════════════════════════════════════════╤═══════════════════════════════════════════════════╗
║ month   │ count_of_ids_seen │ sum_of_(last_seen_stat_for_that_month per ID) │ sum_of_(last_seen_stat_two_for_that_month per ID) ║
╠═════════╪═══════════════════╪═══════════════════════════════════════════════╪═══════════════════════════════════════════════════╣
║ 2019-01 │ 2                 │ 160                                           │ 7                                                 ║
╟─────────┼───────────────────┼───────────────────────────────────────────────┼───────────────────────────────────────────────────╢
║ 2019-02 │ 2                 │ 375                                           │ 13                                                ║
╟─────────┼───────────────────┼───────────────────────────────────────────────┼───────────────────────────────────────────────────╢
║ 2019-03 │ 2                 │ 375                                           │ 13                                                ║
╟─────────┼───────────────────┼───────────────────────────────────────────────┼───────────────────────────────────────────────────╢
║ 2019-04 │ 2                 │ 375                                           │ 13                                                ║
╟─────────┼───────────────────┼───────────────────────────────────────────────┼───────────────────────────────────────────────────╢
║ 2019-05 │ 2                 │ 790                                           │ 27                                                ║
╚═════════╧═══════════════════╧═══════════════════════════════════════════════╧═══════════════════════════════════════════════════╝

Я пробовал оконные функции last_value и могу получитьзаписи, которые появляются, но проблема в том, что мне нужно, чтобы данные отставали, если запись не появляется в таблице.Предполагается, например, для 3-го месяца, что из-за отсутствия записей мы должны взять последнюю просмотренную запись даты до этого.

Мое текущее решение использовало <= join, что является узким местом ипри попытке получить миллионы идентификаторов он слишком медленный и не будет работать со скоростью, которая мне нужна.</p>

Я присоединился к generate_series примерно так:

    FROM
        (SELECT month::date FROM generate_series('2018-03-01'::date, '2019-06-01'::date, '1 month') month) d
    LEFT JOIN
        history h
    ON date_trunc('month', h.updated_at) <= d.month

Есть идеи, как сделать это более эффективно и удалить <= join?Это приводит к тому, что вложенный цикл становится слишком большим.</p>

1 Ответ

0 голосов
/ 13 июня 2019

В Citus мы используем сводные таблицы для создания промежуточных результатов для наших запросов на данных в реальном времени. Вы можете рассчитать агрегаты для каждого дня (или, возможно, часа), а затем использовать эти промежуточные значения для расчета агрегатов по месяцам.

Это решение не избавит вас от необходимости использовать объединения, но стоимость вычислений будет значительно меньше.

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

...