0

我经常使用以下 Oracle SQL 查询来查找两个日期之间的最后一个有效更改日期,但效率不高(全表扫描)。上的主键per_all_people_fperson_id, effective_start_date, effective_end_date

基本上对于用户名(不存储有效日期更改),我想找到与该用户一起使用的员工的详细信息。然而,员工更改是有效存储日期,因此我需要找到从和到日期参数之间的最后一个有效更改日期。

是否有适用于两个日期之间的 Oracle 索引?有没有一个技巧可以用来将现有的主键索引与 from 和 to 日期一起使用?如何编写查询以提高效率?我写的几乎所有查询都会使用这个逻辑。

select fu.user_name, papf.employee_number
from   fnd_user fu
left   outer join
(
   select papf2.person_id,
          max(papf2.effective_start_date) max_effective_start_date
   from   per_all_people_f papf2
   where  papf2.effective_start_date between :P_FROM and :P_TO
   group  by papf2.person_id
)  papf3
on     papf3.person_id = fu.employee_id
left   outer join per_all_people_f      papf
on     papf.person_id = fu.employee_id
and    papf.effective_start_date = papf3.max_effective_start_date

想一想,Oracle 肯定在主键索引effective_start_dateeffective_end_date主键索引上浪费了大量磁盘空间,因为唯一会使用它们的时间是如果您知道effective_start_date.

4

2 回答 2

1

无需加入per_all_people_f两次,改为尝试 ROW_NUMBER。

select fu.user_name, papf3.employee_number
from   fnd_user fu
left   outer join
(
   select papf2.person_id, papf2.employee_number,
          row_number() -- latest date first
          over (partition by papf2.person_id
                order by effective_start_date desc ) as rn
   from   per_all_people_f papf2
   where  papf2.effective_start_date between :P_FROM and :P_TO
)  papf3
on     papf3.person_id = fu.employee_id
and    papf3.rn = 1
于 2017-07-24T09:40:23.910 回答
0

这是另一种选择:

select
fu.user_name,
papf.employee_number
from
fnd_user fu,
(
select distinct
papf.person_id,
min(papf.employee_number) keep (dense_rank last order by papf.effective_start_date) over (partition by papf.person_id) employee_number 
from
per_all_people_f papf
where
papf.effective_start_date between :p_from and :p_to
) papf
where
fu.employee_id=papf.person_id(+)

性能注意事项:如果要列出特定日期范围内的所有用户及其相应的可能人员记录更改,则对两个完整数据集进行哈希联接可能是最佳选择。如果您有大量员工,但其中没有多少员工拥有应用程序用户,那么建议的索引访问/*+ push_pred(papf)*/可能会更好。如果日期范围很小且具有选择性,请在 Effective_start_date 上创建一个索引,让优化器对 fnd_user 和该自定义索引获取的 per_all_people_f 记录进行哈希连接。

判断哪个选项最好,不要看执行时间,打开autotrace,看看哪个选项IO最低。

于 2017-07-25T11:28:35.363 回答