Создание запроса Postgresql, который возвращает только строки с измененными значениями по сравнению с предыдущей строкой, которая ссылается на тот же объект - PullRequest
0 голосов
/ 29 февраля 2020

Допустим, у меня есть следующие данные редактирования в таблице postgresql (графика сделана в Excel, поэтому я могу раскрасить код для удобства просмотра).

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

enter image description here

I хотите сделать запрос SELECT, который возвращает только те правки, которые представляют собой изменение двух рассматриваемых атрибутов.

Так, например, edit_id = 11 меня не интересует, потому что не было никаких изменений ни в object_attr. Но я хочу выбрать edit_id=10, потому что именно тогда obj_one's object_attr_2 изменилось с CCC на BBB. Я также хочу выбрать edit_id=9, потому что именно тогда obj_two attr_2 изменится с XXX -> ZZZ.

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

Как создать запрос для выбора этих записей? Я думаю, что это связано с использованием функций запаздывания или опережающего окна, но у меня возникают проблемы, когда я оборачиваюсь вокруг них.

спасибо!

PS вот содержимое таблицы, если это помогает:

CREATE TABLE public.edits_demo (
    edit_id integer NOT NULL,
    object_id text,
    edit_date timestamp with time zone,
    object_attr_1 text,
    object_attr_2 text,
    edit_attr text
);

INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (11, 'obj_one', '2020-02-20 00:00:00+00', 'AAA', 'BBB', 'foo');
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (10, 'obj_one', '2020-02-19 00:00:00+00', 'AAA', 'BBB', 'bar');
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (9, 'obj_two', '2020-02-18 00:00:00+00', 'QQQ', 'ZZZ', 'irrelevant');
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (8, 'obj_one', '2020-02-17 00:00:00+00', 'AAA', 'CCC', 'irrelevant');
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (7, 'obj_two', '2020-02-16 00:00:00+00', 'QQQ', 'XXX', NULL);
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (6, 'obj_one', '2020-02-15 00:00:00+00', 'AAA', 'CCC', NULL);
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (5, 'obj_one', '2020-02-14 00:00:00+00', NULL, 'CCC', NULL);
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (4, 'obj_two', '2020-02-13 00:00:00+00', 'QQQ', 'XXX', NULL);
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (3, 'obj_two', '2020-02-12 00:00:00+00', 'QQQ', 'XXX', NULL);
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (2, 'obj_two', '2020-02-11 00:00:00+00', 'QQQ', NULL, NULL);
INSERT INTO public.edits_demo (edit_id, object_id, edit_date, object_attr_1, object_attr_2, edit_attr) VALUES (1, 'obj_two', '2020-02-10 00:00:00+00', 'NNN', NULL, NULL);

Ответы [ 2 ]

3 голосов
/ 29 февраля 2020
with t as (
    select
        *,
        (object_attr_1, object_attr_2) is distinct from lag((object_attr_1, object_attr_2)) over (partition by object_id order by edit_id) as changed
    from edits_demo)
select * from t where changed;
2 голосов
/ 29 февраля 2020

Это небольшая поправка в ответе Абелисто на адрес:

также более светлый желтый, которые представляют первые правки для объектов, независимо от значения

Вы позволяют значениям быть NULL. Это означает, что значения могут быть NULL в первой записи - и ответ Абелисто не уловит это. Итак, вам нужна явная проверка для первой строки:

with ed as (
      select ed.*,
              (object_attr_1, object_attr_2) is distinct from
                  lag((object_attr_1, object_attr_2)) over (partition by object_id order by edit_id) as changed,
             row_number() over (partition by object_id order by edit_id) as seqnum
      from edits_demo ed
     )
select ed.*
from ed
where changed or seqnum = 1
order by edit_id desc;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...