patternsqlMinor
Updating open orders from a price list within a range of dates
Viewed 0 times
pricerangeupdatingopendateswithinlistfromorders
Problem
Setup
I've set up an example on rextester and dbfiddle.
Scenario
Price list: Its the products price list, one Products can have more than one active price, even a future price.
Orders Pending orders have a price and an order's date
Every time we add a new price in the list, we must update affected rows of pending orders.
For example if we add:
The new price list must be:
```
+----
I've set up an example on rextester and dbfiddle.
Scenario
Price list: Its the products price list, one Products can have more than one active price, even a future price.
+---------+-------+------------+--------+--------+
| product | price | date_price | base | active |
+---------+-------+------------+--------+--------+
| 0125 | 90 | 01.01.2017 | 1200 | 0 |
| 0125 | 100 | 25.01.2017 | 1000 | 1 |
| 0125 | 110 | 27.02.2017 | 500 | 1 |
+---------+-------+------------+--------+--------+
| 1200 | 140 | 01.01.2017 | 2000 | 0 |
| 1200 | 150 | 01.02.2017 | 1500 | 1 |
| 1200 | 160 | 27.02.2017 | 1000 | 1 |
+---------+-------+------------+--------+--------+Orders Pending orders have a price and an order's date
+---------+------------+-------+--------+
| product | order_date | price | base |
+---------+------------+-------+--------+
| 0125 | 19.02.2017 | 100 | 1000 |
| 0125 | 20.02.2017 | 100 | 1000 |
| 0125 | 21.02.2017 | 100 | 1000 |
| 0125 | 22.02.2017 | 100 | 1000 |
| 0125 | 23.02.2017 | 100 | 1000 |
| 0125 | 28.02.2017 | 110 | 500 |
+---------+------------+-------+--------+
| 1200 | 19.02.2017 | 150 | 1500 |
| 1200 | 20.02.2017 | 150 | 1500 |
| 1200 | 21.02.2017 | 150 | 1500 |
| 1200 | 22.02.2017 | 150 | 1500 |
| 1200 | 23.02.2017 | 150 | 1500 |
| 1200 | 28.02.2017 | 160 | 1000 |
+---------+------------+-------+--------+Every time we add a new price in the list, we must update affected rows of pending orders.
For example if we add:
+---------+-------+------------+--------+--------+
| product | price | date_price | base | active |
+---------+-------+------------+--------+--------+
| 0125 | 105 | 21.02.2017 | 1300 | 1 |
| 1200 | 155 | 21.02.2017 | 1400 | 1 |
+---------+-------+------------+--------+--------+The new price list must be:
```
+----
Solution
I used you dbfiddler code in the following solution that uses CROSS APPLY
declare @price_list table(product varchar(20), price int, date_price datetime, base int, active tinyint);
insert into @price_list values
('0125', 90, '2017-01-01', 1200, 0),
('0125', 100, '2017-01-25', 1000, 1),
('0125', 110, '2017-02-27', 500, 1),
('1200', 140, '2017-01-01', 2000, 0),
('1200', 150, '2017-02-01', 1500, 1),
('1200', 160, '2017-02-27', 1000, 1);
declare @orders table(product varchar(20), order_date datetime, price int, base int);
insert into @orders values
('0125', '2017-02-19', 100, 1000),
('0125', '2017-02-20', 100, 1000),
('0125', '2017-02-21', 100, 1000),
('0125', '2017-02-22', 100, 1000),
('0125', '2017-02-23', 100, 1000),
('0125', '2017-02-28', 110, 500),
('1200', '2017-02-19', 150, 1500),
('1200', '2017-02-20', 150, 1500),
('1200', '2017-02-21', 150, 1500),
('1200', '2017-02-22', 150, 1500),
('1200', '2017-02-23', 150, 1500),
('1200', '2017-02-28', 160, 1000);
declare @new_date_price datetime = '2017-02-21';
-- add a new price to the list
--
insert into @price_list values ('0125', 105, @new_date_price - 1, 1300, 1);
insert into @price_list values ('1200', 155, @new_date_price - 1, 1400, 1);
-- update orders price and base, according products price list date price
--
-- I'd like to avoid use 2 (or more) subqueries
--
UPDATE o
SET o.Price = ca.price
,o.base = ca.base
FROM @Orders o
CROSS APPLY (
SELECT TOP 1 pl.price AS price
,pl.base AS base
FROM @Price_List pl
WHERE pl.product = o.product
AND pl.date_price <= o.order_date
AND active = 1
ORDER BY pl.date_price DESC
) ca
WHERE o.product IN (
'0125'
,'1200'
);--<<< select distinct product from inserted
-- final result
--
select * from @price_list order by product, date_price;
select * from @orders order by product, order_date;Code Snippets
declare @price_list table(product varchar(20), price int, date_price datetime, base int, active tinyint);
insert into @price_list values
('0125', 90, '2017-01-01', 1200, 0),
('0125', 100, '2017-01-25', 1000, 1),
('0125', 110, '2017-02-27', 500, 1),
('1200', 140, '2017-01-01', 2000, 0),
('1200', 150, '2017-02-01', 1500, 1),
('1200', 160, '2017-02-27', 1000, 1);
declare @orders table(product varchar(20), order_date datetime, price int, base int);
insert into @orders values
('0125', '2017-02-19', 100, 1000),
('0125', '2017-02-20', 100, 1000),
('0125', '2017-02-21', 100, 1000),
('0125', '2017-02-22', 100, 1000),
('0125', '2017-02-23', 100, 1000),
('0125', '2017-02-28', 110, 500),
('1200', '2017-02-19', 150, 1500),
('1200', '2017-02-20', 150, 1500),
('1200', '2017-02-21', 150, 1500),
('1200', '2017-02-22', 150, 1500),
('1200', '2017-02-23', 150, 1500),
('1200', '2017-02-28', 160, 1000);
declare @new_date_price datetime = '2017-02-21';
-- add a new price to the list
--
insert into @price_list values ('0125', 105, @new_date_price - 1, 1300, 1);
insert into @price_list values ('1200', 155, @new_date_price - 1, 1400, 1);
-- update orders price and base, according products price list date price
--
-- I'd like to avoid use 2 (or more) subqueries
--
UPDATE o
SET o.Price = ca.price
,o.base = ca.base
FROM @Orders o
CROSS APPLY (
SELECT TOP 1 pl.price AS price
,pl.base AS base
FROM @Price_List pl
WHERE pl.product = o.product
AND pl.date_price <= o.order_date
AND active = 1
ORDER BY pl.date_price DESC
) ca
WHERE o.product IN (
'0125'
,'1200'
);--<<< select distinct product from inserted
-- final result
--
select * from @price_list order by product, date_price;
select * from @orders order by product, order_date;Context
StackExchange Database Administrators Q#165102, answer score: 5
Revisions (0)
No revisions yet.