Запрос последних ненулевых значений таблицы временных рядов в Postgres - PullRequest
0 голосов
/ 01 декабря 2019

У меня есть таблица временных рядов, которая выглядит следующим образом:

time                |   a     | b        | c       | d
--------------------+---------+----------+---------+---------
2016-05-15 00:08:22 |         |          |         |         
2016-05-15 01:50:56 |         |          | 26.8301 |
2016-05-15 02:41:58 |         |          |         |            
2016-05-15 03:01:37 |         |          |         |            
2016-05-15 04:45:18 |         |          |         |         
2016-05-15 05:45:32 |         |          | 26.9688 |
2016-05-15 06:01:48 |         |          |         |         
2016-05-15 07:47:56 |         |          |         | 27.1269
2016-05-15 08:01:22 |         |          |         |            
2016-05-15 09:35:36 | 26.7441 | 29.8398  |         | 26.9981
2016-05-15 10:08:53 |         |          |         |         
2016-05-15 11:08:30 |         |          |         |         
2016-05-15 12:14:59 |         |          |         |         
2016-05-15 13:33:36 | 27.4277 | 29.7695  |         |                            
2016-05-15 14:36:36 | 27.4688 | 29.6836  |         |            
2016-05-15 15:37:36 | 27.1016 |          |         |       

Я хочу вернуть последние ненулевые значения каждого столбца:

вот так (лучший вариант):

time                | column   | value
--------------------+--------- +-------
2016-05-15 15:37:36 | a        | 27.1016
2016-05-15 14:36:36 | b        | 29.6836
2016-05-15 05:45:32 | c        | 26.9688
2016-05-15 09:35:36 | d        | 26.9981

вот так:

column   | value
-------- +-------
a        | 27.1016
b        | 29.6836
c        | 26.9688
d        | 26.9981

или хотя бы вот так:

a       | b        | c       | d
--------+----------+---------+---------
27.1016 | 29.6836  | 26.9688 | 26.9981

Спасибо!

Ответы [ 2 ]

2 голосов
/ 01 декабря 2019

Вы можете отменить поворот и выбрать последнюю строку:

select distinct on (v.which) t.time, v.which, v.val
from t cross join lateral
     (values (a, 'a'), (b, 'b'), (c, 'c'), (d, 'd')) v(val, which)
where v.val is not null
order by v.which, t.time desc;
1 голос
/ 01 декабря 2019

Я предлагаю другой ответ, но теперь я вижу, что ответ @GordonLinoff лучше.

with src as (
  select '0' as pos,    1    as a, 2    as b, null as c
  union all select '1', null as a, null as b, 7    as c
  union all select '2', 2    as a, null as b, 3    as c
  union all select '3', null as a, null as b, null as c
  union all select '4', null as a, 4    as b, null as c
),
n as (
 select row_number() over() as rn, src.* from src
)

(select last_value(pos) over (order by rn desc) as timestamp, 'a' as column, last_value(a) over (order by rn desc) as value 
from n
where a is not null
limit 1)
union all
(select last_value(pos) over (order by rn desc) as timestamp, 'b' as column, last_value(b) over (order by rn desc) as value 
from n
where b is not null
limit 1)
union all
(select last_value(pos) over (order by rn desc) as timestamp, 'c' as column, last_value(c) over (order by rn desc) as value 
from n
where c is not null
limit 1)
timestamp | column | value
:-------- | :----- | ----:
2         | a      |     2
4         | b      |     4
2         | c      |     3

db <> скрипка здесь

...