Reputation: 1
I'm trying to update all values of a column in a table 1 using a value from table 2 that has a corresponding id. The tricky part is that the value I need to pull from table 2 needs to be the 2nd highest date row, which I can use a date column for the 2nd highest date in the table.
This is what I have tried, but this is not an efficient query. I'm wondering if there is a more efficient way of going about this to achieve my goal.
UPDATE table1 tb1
SET newVal = (SELECT DISTINCT val
FROM tb2
WHERE tb1.id = tb2.id
AND date =
(SELECT MAX(date)
FROM tb2
WHERE tb1.id = tb2.id
AND date <
(SELECT MAX(date)
FROM tb2
WHERE tb1.id = tb2.id))),
update_time = SYSDATE
WHERE newVal IS NULL
AND EXISTS (SELECT DISTINCT val
FROM tb2
WHERE tb1.id = tb2.id
AND date =
(SELECT MAX(date)
FROM tb2
WHERE tb1.id = tb2.id
AND date <
(SELECT MAX(date)
FROM tb2
WHERE tb1.id = tb2.id)));
I may be attempting something that is not possible in a single query but any help would be greatly appreciated.
Thanks!
Upvotes: 0
Views: 36
Reputation: 168361
You can use a MERGE
statement and the DENSE_RANK
analytic function:
MERGE INTO table1 t1
USING (
SELECT id,
val,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY val DESC) AS rn
FROM (
SELECT id,
val,
DENSE_RANK() OVER (PARTITION BY id ORDER BY "DATE" DESC) AS rnk
FROM table2
)
WHERE rnk = 2
) t2
ON (t1.id = t2.id AND t2.rn = 1)
WHEN MATCHED THEN
UPDATE
SET newval = t2.val
WHERE newval IS NULL;
Which, for the sample data:
CREATE TABLE table1 (id, newval) AS
SELECT 1, NULL FROM DUAL UNION ALL
SELECT 2, NULL FROM DUAL UNION ALL
SELECT 3, NULL FROM DUAL UNION ALL
SELECT 4, 4 FROM DUAL UNION ALL
SELECT 5, NULL FROM DUAL;
CREATE TABLE table2 (id, "DATE", val) AS
SELECT 1, DATE '2022-01-01', 1.1 FROM DUAL UNION ALL
SELECT 1, DATE '2022-01-02', 1.2 FROM DUAL UNION ALL
SELECT 1, DATE '2022-01-03', 1.3 FROM DUAL UNION ALL
SELECT 2, DATE '2022-01-01', 2.1 FROM DUAL UNION ALL
SELECT 2, DATE '2022-01-02', 2.2 FROM DUAL UNION ALL
SELECT 3, DATE '2022-01-01', 3.1 FROM DUAL UNION ALL
SELECT 4, DATE '2022-01-01', 4.1 FROM DUAL UNION ALL
SELECT 4, DATE '2022-01-02', 4.2 FROM DUAL UNION ALL
SELECT 5, DATE '2022-01-01', 5.1 FROM DUAL UNION ALL
SELECT 5, DATE '2022-01-01', 5.2 FROM DUAL UNION ALL
SELECT 5, DATE '2022-01-02', 5.3 FROM DUAL UNION ALL
SELECT 5, DATE '2022-01-02', 5.4 FROM DUAL;
Then, after the MERGE
, table1
contains:
ID NEWVAL 1 1.2 2 2.1 3 null 4 4 5 5.2
db<>fiddle here
Upvotes: 1