Как проверить пропущенные значения в таблице, представляющей несколько часовых временных рядов (DB2)? - PullRequest
0 голосов
/ 12 марта 2020

Представьте, что у меня есть таблица DB2 с именем FOO с идентификатором временного ряда, значением отметки времени каждого часа и целым числом. Это определение:

CREATE TABLE FOO(
    Id_timeseries      INTEGER NOT NULL,
    number              DECIMAL(10, 3) NOT NULL,
    timestamp          TIMESTAMP NOT NULL,
);

Я хотел бы знать, для каждого временного ряда (представьте, что их несколько), есть ли пустые значения между двумя данными датами и что это за пустые даты (I предположим, что дать диапазон этих значений было бы намного сложнее)

Пример:

Id_timeseries    number     timestamp
1                 28        2017-01-01 01:00:00
1                 28        2017-01-01 02:00:00
1                 28        2017-01-01 03:00:00
2                 28        2017-01-01 01:00:00
2                 28        2017-01-01 02:00:00
2                 28        2017-01-01 03:00:00
1                 28        2017-01-01 07:00:00
1                 28        2017-01-01 06:00:00

И я хочу узнать недостающие значения в часах от 2017:01-01 00:00:00 до 2017:01-02 00:00:00

Выход:

Id_timeseries    from                   to
1                2017:01-01 00:00:00    2017:01-01 00:00:00
1                2017:01-01 04:00:00    2017:01-01 05:00:00
1                2017:01-01 08:00:00    2017:01-01 23:00:00
2                2017:01-01 00:00:00    2017:01-01 00:00:00
2                2017:01-01 04:00:00    2017:01-01 23:00:00

1 Ответ

1 голос
/ 12 марта 2020

Попробуйте:

WITH FOO (Id_timeseries, number, timestamp) AS 
(
VALUES
  (1, 28, timestamp('2017-01-01 01:00:00'))
, (1, 28, timestamp('2017-01-01 02:00:00'))
, (1, 28, timestamp('2017-01-01 03:00:00'))
, (1, 28, timestamp('2017-01-01 06:00:00'))
, (1, 28, timestamp('2017-01-01 07:00:00'))
--, (1, 28, timestamp('2017-01-01 00:00:00'))
--, (1, 28, timestamp('2017-01-01 23:00:00'))
--, (1, 28, timestamp('2017-01-02 00:00:00'))
, (2, 28, timestamp('2017-01-01 01:00:00'))
, (2, 28, timestamp('2017-01-01 02:00:00'))
, (2, 28, timestamp('2017-01-01 03:00:00'))
)
-- Internal gaps
SELECT Id_timeseries, timestamp_prev + 1 hour as from, timestamp - 1 hour as to
FROM
(
SELECT Id_timeseries, timestamp, lag(timestamp) over (partition by Id_timeseries order by timestamp) timestamp_prev
FROM FOO
)
WHERE timestamp_prev <> timestamp - 1 hour
-- Start gap
  UNION ALL
SELECT Id_timeseries, timestamp('2017-01-01 00:00:00') as from, min(timestamp) - 1 hour as to
FROM FOO
GROUP BY Id_timeseries
HAVING timestamp('2017-01-01 00:00:00') <> min(timestamp)
-- End gap
  UNION ALL
SELECT Id_timeseries, max(timestamp) + 1 hour as from, timestamp('2017-01-02 00:00:00') as to 
FROM FOO
GROUP BY Id_timeseries
HAVING timestamp('2017-01-02 00:00:00') <> max(timestamp)
ORDER BY Id_timeseries, from;

Результат:

|ID_TIMESERIES|FROM                      |TO                        |
|-------------|--------------------------|--------------------------|
|1            |2017-01-01-00.00.00.000000|2017-01-01-00.00.00.000000|
|1            |2017-01-01-04.00.00.000000|2017-01-01-05.00.00.000000|
|1            |2017-01-01-08.00.00.000000|2017-01-02-00.00.00.000000|
|2            |2017-01-01-00.00.00.000000|2017-01-01-00.00.00.000000|
|2            |2017-01-01-04.00.00.000000|2017-01-02-00.00.00.000000|
...