Есть сущность и дополнительные атрибуты этой сущности, которые являются историческими:
create table items
(
item_id number not null,
name varchar2 not null,
...
);
create table attributes
(
attr_id number not null,
item_id number not null,
attribute varchar2 not null.
value varchar2,
date_beg date not null,
date_end date
);
Вообще атрибут должен быть уникальным (то есть в таблице атрибутов не должно быть значений с повторяющимися item_id+attribute); если добавляется уже существующий атрибут, то действующий атрибут должен закрыться (date_end=sysdate) и в таблицу атрибутов должна добавиться новая запись:
attr_id | item_id | attribute | value | date_beg | date_end | 1 | 1 | a1 | v1 | 2015-01-01 | 2015-01-10 | 2 | 1 | a1 | v2 | 2015-01-10 | |
|
Но в информационной системе есть небольшая недоработка и в некоторых случаях предыдущий атрибут не закрывается:
attr_id | item_id | attribute | value | date_beg | date_end | 1 | 1 | a1 | v1 | 2015-01-01 | | 2 | 1 | a1 | v2 | 2015-01-10 | |
|
Мне нужно найти такие дубли и закрыть их, оставив самую свежую запись.
Дубли выбираю так:
select ...
from items i
join attributes a on (a.item_id = i.item_id and a.date_beg <= sysdate and nvl(a.date_end,date'9999-01-01') > sysdate)
join attributes d on (d.item_id = i.item_id and d.date_beg <= sysdate and nvl(d.date_end,date'9999-01-01') > sysdate and d.attr_id != a.attr_id and d.attribute = a.attribute)
Как лучше будет закрыть все старые записи?
Добавить к вышеуказанному запросу группировку по item_id, получить max(date_beg), обернуть в подзапрос и сделать update attributes set date_beg = sysdate where attr_id not in (...)?
Или лучше прямо в этом запроса аналитические функции задействовать (partition by)?
________________________
Мы смотрим с оптимизмом...
...в оптический прицел.