我有一个表xx_wr,它有一个我想要的列action_code 根据PER_ASG的action_code列进行更新。
此PER_ASG的列有效_start_date和effective_end_date。 只应选择此表中作为最新记录的max effective_start_date来更新xx_wr。
PER_ASG
EFFECTIVE_START_DATE EFFECTIVE_END_DATE ACTION_CODE PERSON_ID
01-JAN-2016 31-DEC-4712 HR 10
02-FEB-2015 31-DEC-2015 TERM 10
因此,从该表中,应该选择01-JAN-2016的最新行,Action_code HR应该更新WR中的action_code。
我已为此编写了以下查询。但需要3小时才能更新10k行。有什么方法可以修改我的查询以提高性能吗?
update XX_WR wr
set wr.action_code =
(
select pam.action_code
from PER_ASG pam
where 1=1
and pam.person_id=wr.person_id
and pam.effective_start_date = (select max(ppm.effective_start_date) from PER_ASG ppm
where 1=1
and ppm.person_id = pam.person_id
))
where 1=1;
答案 0 :(得分:1)
而不是嵌套的子查询,以找到每个effective_start_date
使用person_id
窗口函数找到它的最大ROW_NUMBER
试试这种方式
MERGE INTO XX_WR AS wr
using (SELECT Row_number()OVER(partition BY person_id ORDER BY effective_start_date DESC ) AS rn,
action_code,
person_id
FROM PER_ASG) pam
ON wr.person_id = pam.person_id
AND pam.rn = 1
WHEN matched THEN
UPDATE SET action_code = pam.action_code;
注意:这里我们不必使用MERGE
,因为我不确定Oracle使用Update from Join
语句中的MERGE
语法但是这个想法是一样的< / p>
答案 1 :(得分:1)
这是查询:
update XX_WR wr
set wr.action_code =
(select pam.action_code
from PER_ASG pam
where pam.person_id = wr.person_id and
pam.effective_start_date =
(select max(ppm.effective_start_date)
from PER_ASG ppm
where ppm.person_id = pam.person_id
)
);
这是更新XX_WR
中的所有行。这可能是性能问题的原因。
但是,仍然可以提高查询效率。我会推荐索引。从PER_ASG(person_id, effective_start_date)
开始。我也会把它重写为:
update XX_WR wr
set wr.action_code =
(select max(pam.action_code) keep (dense_rank first order by effective_date)
from PER_ASG pam
where pam.person_id = wr.person_id
);
答案 2 :(得分:1)
WITH
sub1 AS
( /*+ materialize */
SELECT pam.action_code,pam.person_id
FROM PER_ASG pam
WHERE 1 = 1
AND pam.effective_start_date =
(SELECT MAX (ppm.effective_start_date)
FROM PER_ASG ppm
WHERE 1 = 1 AND ppm.person_id = pam.person_id)
)
update XX_WR wr
set wr.action_code =sub1.action_code
where sub1.person_id=wr.person_id