Presto — Вставка Отсутствующих Меток Времени

#sql #presto

Вопрос:

ИЗМЕНИТЬ: Внес несколько уточнений в сообщение ниже

Я пытаюсь решить проблему, в которой у меня есть таблица с отсутствующими метками времени. Допустим, есть такой стол, как этот:

Отметка времени Числовое поле
2021-10-24 16:59:00.000 101
2021-10-24 16:57:00.000 101

Я хотел бы попробовать и сделать 2 вещи:

  1. Заполните третью запись, где метка времени будет 2021-10-24 16:58:00.000.
  2. Наряду с этим я хотел бы заполнить поле NumericField как 101, если записи о лидерах и задержках совпадают, как в этом примере. Результатом было бы:
Отметка времени Числовое поле
2021-10-24 16:59:00.000 101
2021-10-24 16:58:00.000 101
2021-10-24 16:57:00.000 101

Если записи числового поля «Начало» и «отставание» не совпадают, то сгенерированное числовое поле приведет к нулю. Примером может быть:

Отметка времени Числовое поле
2021-10-24 16:59:00.000 101
2021-10-24 16:58:00.000 нулевой
2021-10-24 16:57:00.000 100

Причина, по которой я публикую этот вопрос, заключается в том, что рекурсивные CTE не поддерживаются в Presto, и я не смог найти хороших ресурсов, которые помогли бы мне решить эту проблему.

Ответ №1:

Я бы попробовал использовать lag для поиска предыдущих значений, а затем sequence сгенерировать массив дат с interval '1' minute шагом, отменить его и объединить результат с исходной таблицей:

 WITH dataset (Timestamp, NumericField) AS (
    VALUES (timestamp '2021-10-24 16:59:00.000', 101),
        (timestamp '2021-10-24 16:57:00.000', 101),
        (timestamp '2021-10-24 16:55:00.000', 99)
)
SELECT date as Timestamp,
    val as NumericField
FROM (
        SELECT array_except(
                sequence(prev_ts, Timestamp, interval '1' minute),
                array [ prev_ts, timestamp ] -- exclude border values
            ) as dates,
            case
                NumericField
                when prev_num then prev_num
            end as val
        FROM (
                SELECT *,
                    lag(Timestamp) over(order by Timestamp) prev_ts,
                    lag(NumericField) over(order by Timestamp) prev_num
                FROM dataset
            )
    ) seq
    CROSS JOIN UNNEST(dates) AS t (date)
UNION
SELECT *
FROM dataset
ORDER BY timestamp
 

Выход:

Отметка времени Числовое поле
2021-10-24 16:55:00.000 99
2021-10-24 16:56:00.000
2021-10-24 16:57:00.000 101
2021-10-24 16:58:00.000 101
2021-10-24 16:59:00.000 101

Комментарии:

1. Очень ценю это. Мне нравится использование последовательности для обработки этого конкретного случая использования. Большое вам за это спасибо!

2. Единственный вопрос, который у меня есть, заключается в том, как работает только использование ЛАГА при ожидании следующей записи? Я предположил, что использование сочетания LEAD() и LAG() было бы подходящим подходом @Guru Stron

3. @user7298979 вам не потребуется сочетание обеих причин lag / lead используются против существующих данных (например, «предыдущий» и «следующий» значения не будут меняться в течение всего разрыв), так что вы можете взять одну из функций (или lag , или lead ) для расчета и comape результат с текущим значением которых является «Next» (или «предыдущая» в lead ) на разрыв.

4. Итак, для второго примера в моем вопросе он все равно вернет нулевое значение?

5. @user7298979 да, значение для 2021-10-24 16:56:00.000 метки времени представляет именно это.