Как пересечь историю при объединении таблиц? - PullRequest
0 голосов
/ 07 марта 2020

Существует две таблицы:

Таблица1 (id, param1, param2, date_from, date_to):

(1, 'z', 55, '01.05.2010 12:30:20', '17.05.2010 13:10:14'),
(1, 'c', null, '17.05.2010 13:10:15', '18.01.2010 04:13:15'),
(1, 'c', 25, '18.01.2010 04:13:16', '01.01.9999 00:00:00');

Table2 (id, param3, date_from, date_to):

(1, 15, '01.04.2010 12:30:20', '02.05.2010 13:10:14'),
(1, 35, '02.05.2010 13:10:15', '01.01.9999 00:00:00');

Необходимо, чтобы при объединении 2 таблиц были поля, содержащие историю изменений каждого параметра. То есть:

Выбрать (id, param1, param2, param3, date_from, date_to):

(1, null, null, 10, '01.04.2010 12:30:20', '01.05.2010 12:30:19'),
(1, 'z', 55, 15, '01.05.2010 12:30:20', '02.05.2010 13:10:14'),
(1, 'z', 55, 35, '02.05.2010 13:10:15', '17.05.2010 13:10:14'),
(1, 'c', null, 35, '17.05.2010 13:10:15', '18.01.2010 04:13:15'),
(1, 'c', 25, 35, '18.01.2010 04:13:16', '01.01.9999 00:00:00');

Где записи из двух таблиц не перекрываются во времени (или части времени), должен быть выведен ноль.

Пока я сделал:

SELECT a.id, param1, param2, param3, a.dfrom as afrom, a.dto as ato, b.dfrom as bfrom, b.dto as bto
FROM Table1 a LEFT JOIN Table2 b ON a.id = b.id
UNION
SELECT id, null as param1, null as param2, param3, null as afrom, null as bfrom, dfrom, dto
FROM Table2

И тогда я не понимаю, как действовать ...

1 Ответ

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

Идея решения этой проблемы заключается в деконструкции данных в «события», которые присваивают значения параметрам. Затем восстановите историю, используя функции агрегации и окна.

Поскольку у вас есть допустимые значения NULL, это немного сложно, но я думаю, что следующее делает то, что вы хотите:

with t as (
      select t1.id, t1.param1, t1.param2, null as param3, t1.date_from, 1 as which
      from table1 t1
      union all
      select t2.id, null as param1, null as param2, t2.param3, t2.date_from, 2 as which
      from table2 t2
     )
select t.id, dfrom,
       lead(dfrom, 1, '9999-01-01'::timestamp) over (partition by id order by dfrom) as dto,
       max(param1) over (partition by param1_grp) as param1,
       max(param2) over (partition by param2_grp) as param2,
       max(param3) over (partition by param3_grp) as param3
from (select id, max(param1) as param1, max(param2) as param2,
             max(param3) as param3, dfrom,
             count(*) filter (where which = 1) over (partition by id order by dfrom) as param1_grp,
             count(*) filter (where which = 1) over (partition by id order by dfrom) as param2_grp,
             count(*) filter (where which = 2) over (partition by id order by dfrom) as param3_grp
      from t
      group by id, dfrom
     ) t
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...