I have 2 tables:
First one is bom
Article |
---|
AB |
CD |
EF |
GH |
CREATE TABLE bom
(
Article VARCHAR(250)
);
INSERT INTO bom (Article)
VALUES
('AB'),
('CD'),
('EF'),
('GH');
Second one is purchases
Article | OrderDate | Price |
---|---|---|
AB | ‘2020-01-10’ | 12 |
AB | ‘2020-01-05’ | 10 |
AB | ‘2020-01-03’ | 8 |
EF | ‘2020-01-01’ | 7 |
CREATE TABLE purchases
(
Article VARCHAR(250),
OrderDate DATE,
Price DOUBLE
);
INSERT INTO purchases (Article, OrderDate, Price)
VALUES
('AB', '2020-01-10', 12.0),
('AB', '2020-01-05', 10.0),
('AB', '2020-01-03', 8.0),
('EF', '2020-01-01', 7.0);
I want to extract the most recent price for each row of Article
at a given date.
For instance, at @evalDay = '2020-01-04'
, I want to get
Article | OrderDate | Price |
---|---|---|
AB | ‘2020-01-03’ | 8 |
EF | ‘2020-01-01’ | 7 |
I’ve managed it to work using a window function (row_number() over
), but the performance is not as good as I need. This is a simplified example, but my bom
table has a few hundred of rows, whereas the purchases
has about 1 million rows. On my computer, it takes approx. 50ms to execute. Of course I use indexes and compound indexes.
My solution:
set @evalDay = '2020-01-04';
with cte (Article, OrderDate, Price, rn) as (
select purchases.*,
row_number() over (
partition by bom.article
order by purchases.OrderDate desc
) as rn
from bom
join purchases on bom.Article = purchases.Article
where purchases.OrderDate <= @evalDay
)
select *
from cte
where rn = 1;
In this case, what’s the fastest approach to get the answer?
2
Answers
I would try the following approaches:
bom
If the above still doesn’t perform, consider creating a table to store the result (
Article
,OrderOdate
,Price
,evalDate
) partitioned byevalDate
.If you have more than one row in purchases which has the same latest date for the same Article, this might not give you what you want but it’s a fairly simple query….