tags:

views:

62

answers:

3

The best way of describing this is I have a table of people with their names and ages. Assume that people with the same surname are from the same family. I need a query in oracle which will retrieve a list of the oldest person in each family, but not older than a certain age.

Table: person

name      surname         age
===============================
James     Smith           23
Sarah     Powell          17
Barry     Smith           31
Mark      Smith           35
Mary      Smith           18
Bob       Powell          30

How do I retrieve the oldest person in each family under 30?

Results I'm after

name      surname         age
===============================
James     Smith           23
Sarah     Powell          17
+3  A: 
select p.*
from person p
inner join (
    select surname, max(age) as maxage
    from person 
    where age < 30
    group by surname
) pm on p.surname = pm.surname and p.age = pm.maxage
RedFilter
A: 

This version will only require one pass through the data:

SELECT DISTINCT
       FIRST_VALUE(name)
       OVER (PARTITION BY surname ORDER BY age DESC) name
      ,FIRST_VALUE(surname)
       OVER (PARTITION BY surname ORDER BY age DESC) surname
      ,FIRST_VALUE(age)
       OVER (PARTITION BY surname ORDER BY age DESC) age
FROM   person
WHERE  age < 30;

Warning: in the event of a tie (i.e. two people with identical ages in the same family), it will just pick one.

Jeffrey Kemp
Interesting - never seen the `FIRST_VALUE` syntax before, when did Oracle start supporting it?
OMG Ponies
Since 8i I think - 9i does: http://download.oracle.com/docs/cd/B10501_01/server.920/a96540/functions46a.htm#SQLRF00642
Jeffrey Kemp
A: 
Stellios