Intro
I have a complex query I need to write (for an Oracle DB). I’ve tried to make an analogy to avoid using company data, so let me know if something seems weird.
Tables
CAT
- CAT_ID (PK)
KITTEN
- KITTEN_ID (PK)
CAT_KITTEN_PLAY
- PLAY_ID (PK)
- CAT_ID (FK to CAT table)
- KITTEN_ID (FK to KITTEN table)
- KITTEN_GENDER (String – M or F)
- PLAY_TIME (Date)
KITTEN_INFO
- KITTEN_ID (FK to KITTEN table)
- NAME (String, e.g. “Name”)
- VALUE (String, e.g. “Duchess”)
Description
So basically, the CAT and KITTEN tables just hold IDs and some other random information. KITTEN_INFO holds the name of the kittens (among other things). And CAT_KITTEN_PLAY logs all of the times a cat plays with a kitten.
What I need, is to write a query that returns all of the CATs whose most recent play time with a male KITTEN was in a certain date range. Let’s call it Jan 1 2011 to Jan 31 2011. I also need to include the play date and name of the most recent male and female kitten the cat played with.
So Far
Below is what I have so far:
SELECT cat.*, lastMale.PLAY_TIME maleTime, lastFemale.PLAY_TIME femaleTime, maleName.VALUE male, femaleName.VALUE female
FROM CAT cat
LEFT JOIN CAT_KITTEN_PLAY lastMale ON lastMale.CAT_ID = cat.CAT_ID
AND lastMale.GENDER = 'M'
LEFT JOIN CAT_KITTEN_PLAY lastFemale ON lastFemale.CAT_ID = cat.CAT_ID
AND lastFemale.GENDER = 'F'
LEFT JOIN KITTEN_INFO femaleName ON femaleName.KITTEN_ID = lastFemale.KITTEN_ID
AND maleName.NAME = 'Name'
LEFT JOIN KITTEN_INFO maleName ON maleName.KITTEN_ID = lastMale.KITTEN_ID
AND femaleName.NAME = 'Name'
WHERE lastMale.PLAY_TIME BETWEEN '01-JAN-2011 12:00:00 AM'
AND '31-JAN-2011 11:59:59 PM'
Problems
This does not account for the fact that a cat may have played with a make/female kitten more than once. So, I’d want to add “AND lastMale.PLAY_TIME = (SELECT MAX(PLAY_TIME) FROM CAT_KITTEN_PLAY WHERE CAT_ID = cat.ID AND KITTEN_GENDER = ‘M’)” onto the first join, and a similar one to the second join. But subqueries are not allowed on joins.
Any thoughts? Note that a cat may have never played with a female kitten. But the cat should still be included if they meet the criteria (hence the left joins).
Analytic functions are probably the best answer to your problem: