#sql #presto
Вопрос:
ИЗМЕНИТЬ: Внес несколько уточнений в сообщение ниже
Я пытаюсь решить проблему, в которой у меня есть таблица с отсутствующими метками времени. Допустим, есть такой стол, как этот:
Отметка времени | Числовое поле |
---|---|
2021-10-24 16:59:00.000 | 101 |
2021-10-24 16:57:00.000 | 101 |
Я хотел бы попробовать и сделать 2 вещи:
- Заполните третью запись, где метка времени будет 2021-10-24 16:58:00.000.
- Наряду с этим я хотел бы заполнить поле 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
метки времени представляет именно это.