Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Mailing Lists -> Oracle-L -> Re: trouble with sql
Hi Chris,
This is exactly what the FIRST and LAST aggregate functions are for. The syntax is ... not immediately obvious (to put it nicely), but the functions are specifically designed for this problem. I've made a few assumptions about your table structure below (such as non-nullable ps.changeDate), but hopefully you get the idea:
select p.periodID
, ps.projectNumber , max(ps.changeDate) as changeDate , max(ps.statusID) keep (
dense_rank first
order by ps.changeDate desc
) as statusID
from period p
, projectStatus ps
where ps.changeDate >= trunc(p.startDate)
and trunc(ps.changeDate) <= p.endDate
group by p.periodID
, ps.projectNumber
/
To paraphrase, the query says:
1. Group by the p.periodID and ps.projectNumber. 2. For each group, return the max ps.changeDate as changeDate. 3. For each group, also order the rows within the group by the ps.changeDatedescending. Rank these rows using the dense_rank function and keep the SET of rows which rank first by the given sorting specification (if the grouping fields are indeed a primary / unique key, this set consists of only one row). 4. Return the maximum ps.statusID from this set.
I find these functions extremely useful, as this is a requirement which often pops up... no more self-joins!
Hope that helps.
cheers,
Anthony
Quoting "Stephens, Chris" <chris_stephens_at_admworld.com>:
> There has got to be a way to do this but I can't find the syntax.
>
> Essentially I need the max of column 3 grouped by column 1 and 2 and
> also the value of column 4 that corresponds to the returned columns 1,2,
> and 3.
>
> Here is the actual sql that I believe to be using an unnecessary join:
>
> select ps2.periodID, ps2.projectNumber, ps2.changeDate, ps3.statusID
> from ( select p.periodID, ps.projectNumber, max(ps.changeDate) as
> changeDate
> from period p, projectStatus ps
> where ps.changeDate >= trunc( p.startDate )
> and trunc( ps.changeDate ) <= p.endDate
> group by p.periodID, ps.projectNumber ) ps2, projectStatus ps3
> where ps2.projectNumber = ps3.projectNumber and ps2.changeDate =
> ps3.changeDate
>
> Is there a better way to write this?
-- http://www.freelists.org/webpage/oracle-lReceived on Wed Jan 03 2007 - 21:34:55 CST