Как в ClickHouse при выравнивании показаний датчиков по меткам времени с нужным шагом вместо 0 получить предыдущее реальное показание датчика?

  1. В ClickHouse для хранения показаний датчиков создана таблица indications со следующей структурой:
CREATE TABLE indications (
  `unit_id` UInt16 CODEC(DoubleDelta, ZSTD(1)),
  `sensor_name` String CODEC(ZSTD(1)),
  `date_time_utc` DateTime('UTC') CODEC(Delta(4), ZSTD(1)),
  `period_sec` UInt32 CODEC(DoubleDelta, ZSTD(1)),
  `indication` Decimal(18, 7) CODEC(Delta(8), ZSTD(1))
) ENGINE = ReplacingMergeTree() PARTITION BY (unit_id, toYYYYMM(date_time_utc), period_sec)
ORDER BY
  (unit_id, sensor_name, date_time_utc, period_sec) SETTINGS index_granularity = 8192
  1. Строки в таблицу добавляются только при изменении показания датчика.
  2. Для отладки запросов добавим в таблицу indications следующие тестовые показания датчика:
insert into indications values
(8, 'First', '2021-04-01 00:00:00', 1, 0),
(8, 'First', '2021-04-01 05:00:00', 1, 5),
(8, 'First', '2021-04-01 08:00:00', 1, 8),
(8, 'First', '2021-04-01 08:20:00', 1, 6),
(8, 'First', '2021-04-01 08:40:00', 1, 7),
(8, 'First', '2021-04-01 09:00:00', 1, 0),
(8, 'First', '2021-04-01 11:00:00', 1, 11),
(8, 'First', '2021-04-01 13:00:00', 1, 0)
  1. Для выравнивания показаний датчиков по меткам времени с нужным шагом (например в 1 час) использую конструкцию ORDER BY ... WITH FILL
select
    i.date_time_utc,
    i.indication,
    neighbor(i.indication, -1) as prev_ind,
    neighbor(i.date_time_utc, -1) as prev_date
from
    indications as i
where
    i.unit_id = 8
    and i.sensor_name = 'First'
    and i.date_time_utc >= '2021-04-01 00:00:00'
order by i.date_time_utc with fill step 60*60

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

date_time_utc indication prev_ind prev_date
2021-04-01 00:00:00 0 0 0000-00-00 00:00:00
2021-04-01 01:00:00 0 0 0000-00-00 00:00:00
2021-04-01 02:00:00 0 0 0000-00-00 00:00:00
2021-04-01 03:00:00 0 0 0000-00-00 00:00:00
2021-04-01 04:00:00 0 0 0000-00-00 00:00:00
2021-04-01 05:00:00 5 0 2021-04-01 00:00:00
2021-04-01 06:00:00 0 0 0000-00-00 00:00:00
2021-04-01 07:00:00 0 0 0000-00-00 00:00:00
2021-04-01 08:00:00 8 5 2021-04-01 05:00:00
2021-04-01 08:20:00 6 8 2021-04-01 08:00:00
2021-04-01 08:40:00 7 6 2021-04-01 08:20:00
2021-04-01 09:00:00 0 7 2021-04-01 08:40:00
2021-04-01 10:00:00 0 0 0000-00-00 00:00:00
2021-04-01 11:00:00 11 0 2021-04-01 09:00:00
2021-04-01 12:00:00 0 0 0000-00-00 00:00:00
2021-04-01 13:00:00 0 11 2021-04-01 11:00:00
  1. Чтобы отличить реальные нулевые показания датчиков от строк пустышек добавил колонку ind в которой нулевые значения, требующие замены на предыдущие показания, заменены на -1
select
    aligned.*,
    if(aligned.indication=0 and aligned.prev_ind=0, toDecimal64(-1,7), aligned.indication) as ind
from
(
select
    i.date_time_utc,
    i.indication,
    neighbor(i.indication, -1) as prev_ind,
    neighbor(i.date_time_utc, -1) as prev_date
from
    indications as i
where
    i.unit_id = 8
    and i.sensor_name = 'First'
    and i.date_time_utc >= '2021-04-01 00:00:00'
order by i.date_time_utc with fill step 60*60
) as aligned
date_time_utc indication prev_ind prev_date ind
2021-04-01 00:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 01:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 02:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 03:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 04:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 05:00:00 5 0 2021-04-01 00:00:00 5
2021-04-01 06:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 07:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 08:00:00 8 5 2021-04-01 05:00:00 8
2021-04-01 08:20:00 6 8 2021-04-01 08:00:00 6
2021-04-01 08:40:00 7 6 2021-04-01 08:20:00 7
2021-04-01 09:00:00 0 7 2021-04-01 08:40:00 0
2021-04-01 10:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 11:00:00 11 0 2021-04-01 09:00:00 11
2021-04-01 12:00:00 0 0 0000-00-00 00:00:00 -1
2021-04-01 13:00:00 0 11 2021-04-01 11:00:00 0

Подскажите пожалуйста, как в колонке ind вместо -1 получить предыдущее реальное показание датчика ?


Ответы (0 шт):