65 lines
2.4 KiB
SQL
65 lines
2.4 KiB
SQL
-- тестовый набор данных - искать в реальном наборе тягостно
|
|
drop table if exists siv cascade;
|
|
create table siv (
|
|
siv_id int NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
|
|
line_key varchar(255) NOT NULL,
|
|
dt_from date NOT NULL,
|
|
agreement_version int NOT NULL,
|
|
line_version int NOT NULL,
|
|
cost int NULL,
|
|
descr text NULL
|
|
);
|
|
insert into siv (line_key,dt_from,agreement_version,line_version,cost)
|
|
values
|
|
('line-01', '2025-03-01', 1, 1, 100),
|
|
('line-01', '2025-04-01', 1, 2, 100), -- сдвиг на месяц позже
|
|
('line-01', '2025-02-01', 2, 1, 200), -- сдвиг на 2 месяца раньше и увеличение
|
|
('line-01', '2025-05-01', 3, 1, 250), -- сдвиг на 3 месяца позже и увеличение
|
|
('line-01', '2025-05-01', 3, 2, 130), -- уменьшение без сдвига
|
|
('line-01', '2025-06-01', 4, 1, 160) -- сдвиг и увеличение
|
|
;
|
|
select s.*, (select )
|
|
from siv s
|
|
|
|
--https://stackoverflow.com/questions/74296984/how-can-i-discard-rows-that-are-out-of-order
|
|
SELECT *,
|
|
LEAD(dt_from) OVER (PARTITION BY line_key ORDER BY dt_from) dt_next
|
|
FROM
|
|
(
|
|
SELECT *,
|
|
MIN(dt_from) OVER (PARTITION BY line_key ORDER BY agreement_version desc,line_version desc) mn
|
|
|
|
FROM siv
|
|
) t
|
|
WHERE t.dt_from=t.mn
|
|
order by siv_id
|
|
;
|
|
-- демонстрирует коллизию совпадающих дат
|
|
-- для совпадающих дат нам просто нужно взять старшую
|
|
|
|
SELECT *,
|
|
(select min(dt_from) from siv i where i.dt_from > t.dt_from AND i.line_key=t.line_key) dt_next
|
|
FROM
|
|
(
|
|
SELECT *,
|
|
MIN(dt_from) OVER (PARTITION BY line_key ORDER BY agreement_version desc,line_version desc) mn
|
|
FROM siv
|
|
) t
|
|
WHERE t.dt_from=t.mn -- получаем лесенку, в которой порядок дат соответствует порядку версий
|
|
order by siv_id
|
|
;
|
|
|
|
SELECT *,
|
|
LEAD(dt_from) OVER (PARTITION BY line_key ORDER BY dt_from, agreement_version,line_version) dt_next
|
|
FROM
|
|
(
|
|
SELECT *,
|
|
MIN(dt_from) OVER (PARTITION BY line_key ORDER BY agreement_version desc,line_version desc) mn
|
|
|
|
FROM siv
|
|
) t
|
|
WHERE t.dt_from=t.mn
|
|
order by siv_id
|
|
;
|
|
-- в данном случае siv_id=4 имеет нулевой интервал и не будет учтена в расчетах, хотя и даст лишнее чтение
|
|
-- вместо null мы можем взять верхнюю границу диапазона |