Reputation: 1
I have two tables : 1.Actions : Contains multiple actions performed on orderIDs on specific dates. For each orderID, there are multiple rows, each representing a different action performed on a particular date. 2. Logs : Logs orderIDs as "in stock" with specific dates.
Here is the structure of my actions table :
orderID1 | 2024-09-06 | action3
orderID1 | 2024-09-06 | action2.5
orderID1 | 2024-09-05 | action2
orderID1 | 2024-09-05 | action1.5
orderID1 | 2024-09-04 | action1
orderID2 | 2024-09-08 | action23
orderID2 | 2024-09-08 | action22
orderID2 | 2024-09-07 | action21
And here is the structure of my logs table :
orderID1 | 2024-09-06 | ...
orderID1 | 2024-09-05 | ...
orderID1 | 2024-09-04 | ...
orderID2 | 2024-09-08 | ...
orderID2 | 2024-09-07 | ...
I would like to have - for each orderID and date of the Logs table - the most recent action performed on the same orderID on or before that date.
So to say I would like to get the following result
orderID1 | 2024-09-06 | ... | action3
orderID1 | 2024-09-05 | ... | action2
orderID1 | 2024-09-04 | ... | action1
orderID2 | 2024-09-08 | ... | action23
orderID2 | 2024-09-07 | ... | action21
I used the SQL script below with a WINDOW function but it doesn't work. The query fetches the latest action overall for each orderID, instead of fetching the most recent action up to the specific date for each row in the Logs table
WITH latest_actions AS (
SELECT
act.orderID,
lg.logdate,
act.actiondate AS last_action_date,
act.actionname AS action_performed,
ROW_NUMBER() OVER (PARTITION BY act.orderID, lg.logdate
ORDER BY act.actiondate DESC) AS ranked
FROM
Actions act
LEFT JOIN
Logs lg
ON
CAST(lg.logdate AS INTEGER) = act.orderID
WHERE
act.actiondate <= lg.logdate
)
SELECT
lg.orderID,
lg.logdate,
lg.orderdate,
lg.perimeter,
lg.ordertype,
la.last_action_date,
la.action_performed
FROM
Logs lg
LEFT JOIN (
SELECT
orderID,
logdate,
last_action_date,
action_performed
FROM latest_actions
WHERE ranked = 1
) la
ON
CAST(lg.orderID AS INTEGER) = la.orderID
ORDER BY
lg.orderID, lg.logdate
Upvotes: 0
Views: 33
Reputation: 1985
Can you try this:
DROP TABLE IF EXISTS #actions
CREATE TABLE #actions (OrderId varchar(20) NOT NULL, OrderDate Date, ActionName varchar(100))
INSERT INTO #actions (OrderId, OrderDate, ActionName)
VALUES
('orderID1', '2024-09-06', 'action3')
, ('orderID1', '2024-09-06', 'action2.5')
, ('orderID1', '2024-09-05', 'action2')
, ('orderID1', '2024-09-05', 'action1.5')
, ('orderID1', '2024-09-04', 'action1')
, ('orderID2', '2024-09-08', 'action23')
, ('orderID2', '2024-09-08', 'action22')
, ('orderID2', '2024-09-07', 'action21')
DROP TABLE IF EXISTS #logs
CREATE TABLE #logs (OrderId varchar(20) NOT NULL, OrderDate Date)
INSERT INTO #logs (OrderId, OrderDate)
VALUES
('orderID1', '2024-09-06')
, ('orderID1', '2024-09-05')
, ('orderID1', '2024-09-04')
, ('orderID2', '2024-09-08')
, ('orderID2', '2024-09-07')
select * from #actions
select * from #logs
select *
from
( select ROW_NUMBER() over (partition by a.orderdate, a.orderid order by a.orderdate, a.orderid) as rownm, a.*
from #logs l
left join #actions a on l.OrderId = a.OrderId and l.OrderDate = a.OrderDate ) tbl
where tbl.rownm = 1
Upvotes: 0