Дано: таблица с ценами на товары:
id - идентификатор товара
active_from - дата начала активности цены
active_to - срок до которого цена актуальна (может быть null, тогда считается бессрочная)
price - цена
требуется запросом вытащить цены товаров на конкретную дату (но в целом достаточно на текущий момент) и предыдущую цену, чтобы показать снизилась ли цена товара
Важно!
нужно не только актуальную, но и предыдущую.
интервалы активности могут пересекаться по разному, например: был товар у которого цена не менялась пол года, пришли менеджеры и решили сделать скидку до конца месяца, а после истечения скидки чтобы цена вернулась на прежнюю позицию, а за неделю до истечения срока ставят цену ещё ниже и до конца следующего месяца
допустим есть такие данные:
id | active_from | active_to | price
1 | 2019-01-01 | null | 200
1 | 2019-10-01 | null | 150
1 | 2019-11-01 | 2020-11-30 | 100
2 | 2019-01-01 | null | 200
2 | 2019-06-01 | 2019-08-31 | 150
2 | 2019-07-01 | 2019-09-30 | 140
2 | 2019-11-01 | null | 100
таким образом для первого товара в период с января по сентябрь цена 200, предыдущая: null
в октябре цена 150, предыдущая 200
в ноябре цена 100, предыдущая 150
начиная с декабря цена 150, предыдущая 100 (в декабре закончилась акция на товар и активной становится предыдущая активная цена)
для второго товара:
с января 200, null
в июне 150, 200
с июля по сентябрь 140, 150
в октябре 200, 140
с ноября 100, 200
пример запроса:
WITH
prices (row_id, product_id, active_from, active_to, price) AS (
VALUES
(1, 1, '2019-01-01'::date, null, 200),
(2, 1, '2019-10-01'::date, null, 150),
(3, 1, '2019-11-01'::date, '2019-11-30'::date, 100),
(4, 2, '2019-01-01'::date, null, 200),
(5, 2, '2019-06-01'::date, '2019-08-31'::date, 150),
(6, 2, '2019-07-01'::date, '2019-09-30'::date, 140),
(7, 2, '2019-11-01'::date, null, 100),
(8, 3, '2019-01-01'::date, null, 200),
(9, 3, '2019-06-01'::date, '2019-10-31'::date, 150),
(10, 3, '2019-07-01'::date, '2019-09-30'::date, 140),
(11, 3, '2019-11-01'::date, null, 100)
)
SELECT DISTINCT ON (product_id) *, lag("price") OVER (PARTITION BY "product_id" ORDER BY "active_from")
FROM prices
WHERE now() BETWEEN "active_from" AND coalesce("active_to", now())
ORDER BY product_id, "active_from" DESC
беда запроса в том, что отсекаются цены с истёкшими интервалами, поэтому предыдущую цену вытянуть не могу