I have an oracle query that works like this:
SELECT *
FROM VW_REQUIRED r
JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
Required is a view detailing all required training materials, Actual is a view detailing the most recent taking of the given courses. Each of these queries by themselves take under 2 seconds to generate between 10k and 100k rows.
What I want to do is something like:
SELECT *
FROM VW_REQUIRED r
WHERE NOT EXISTS ( SELECT 1 FROM VW_ACTUAL a WHERE a.person_id = r.person_id AND a.target_id = r.target_id)
and it takes more than 20 seconds (I didn't let it finish, because that is obviously too long.
So then I decided to do something different, I made the original JOIN a left join so it will show me all required training, and the actual training only if it exists.
That worked, and was super fast still.
But I want a list of just the courses where there is no actual training attached (i.e. the people we need to kick into gear and get their training...)
When I try something like
SELECT *
FROM VW_REQUIRED r
LEFT JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
WHERE r.person_id = null
I get no rows back. I'm not sure I can filter out the rows where I have no actual results. Normally I'd use WHERE NOT EXISTS
but the performance on it was super slow (and I don't think I can put an index on a view...)
I've managed to make some changes that works, but it seems hacky and I'm sure there's a better solution.
SELECT
who, where_from, mand, target_id, grace_period, date_taken
FROM (
SELECT
r.person_id who,
r.where_from where_from,
r.mand mand,
r.target_id target_id
r.grace_period grace_period,
nvl(a.date_taken, to_date('1980/01/01','yyyy/mm/dd')) date_taken
FROM VW_REQUIRED r
LEFT JOIN VW_ACTUAL a ON a.person_id = r.person_id AND a.target_id = r.target_id
)
WHERE date_taken = to_date('1980/01/01','yyyy/mm/dd')