Home:ALL Converter>Oracle SQL - Finding the last date effective change between two dates efficiently

Oracle SQL - Finding the last date effective change between two dates efficiently

Ask Time:2017-07-24T17:08:34         Author:Superdooperhero

Json Formatter

I am using the following Oracle SQL query frequently to find the last date effective change between two dates but it is not very efficient (full table scans). The primary key on per_all_people_f is person_id, effective_start_date, effective_end_date.

Basically for a user name (which does not store date effective changes) I would like to find the detail of the employee which goes with that user. Employee changes are however stored date effectively and therefore I need to find the last date effective change between the from and to date parameters.

Is there an Oracle index that works with between two dates? Is there a trick I can use to use the existing primary key index with the from and to dates? How can I write the query to be more efficient? Almost all queries I write will use this logic.

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

Come to think of it Oracle must be wasting a lot of disk space on that effective_start_date and effective_end_date in the primary key index, since the only time they would be used is if you know a date for effective_start_date.

Author:Superdooperhero,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/45276487/oracle-sql-finding-the-last-date-effective-change-between-two-dates-efficientl
dnoeth :

There's no need to join per_all_people_f twice, try ROW_NUMBER instead.\n\nselect fu.user_name, papf3.employee_number\nfrom fnd_user fu\nleft outer join\n(\n select papf2.person_id, papf2.employee_number,\n row_number() -- latest date first\n over (partition by papf2.person_id\n order by effective_start_date desc ) as rn\n from per_all_people_f papf2\n where papf2.effective_start_date between :P_FROM and :P_TO\n) papf3\non papf3.person_id = fu.employee_id\nand papf3.rn = 1\n",
2017-07-24T09:40:23
yy