Oracle SQL - 有效地查找两个日期之间的最后日期有效更改

时间:2017-07-24 09:08:35

标签: sql oracle indexing oracle-ebs

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

基本上对于用户名(不存储日期有效更改)我想找到与该用户一起使用的员工的详细信息。但是,员工更改会有效地存储日期,因此我需要查找from和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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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记录的散列连接。

要判断哪个选项最佳,请不要查看执行时间,打开自动跟踪并检查哪个选项的IO最低。