Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Top row by group 2

Status
Not open for further replies.

peterswan

Programmer
Sep 25, 2002
263
US
Hello,

Does anyone know how to select the top row of each group, and display all the records in the table for that row, without writing a subquery?

For example, my table has a date field and a location field, plus several other records. I want to run a query that gets all of the fields for the most recent date, per location.

This only gets the location and the date, but no extra fields:

select max(mc_date), mc_location
from csq_mc
group by mc_location

and if I add the extra fields to the SELECT statement, then ALL of the records are returned.

Can I get just the top date by location, plus the location, plus the other records?

Thanks,[smile]

Peter
 
Try the following

SELECT c.*
FROM
csq_mc c,
(SELECT mc_location, MAX(mc_date) max_date
FROM csq_mc GROUP BY mc_location) m
WHERE c.mc_location = m.mc_location
AND c.mc_date = m.max_date;

RESULTS:
Code:
SQL>   create table csq_mc
  2      (mc_date date,
  3       mc_location varchar2(10),
  4       field1 varchar2(5),
  5       field2 varchar2(5),
  6      field3 varchar2(5))
  7  ;

Table created.

SQL> select * from csq_mc;

MC_DATE   MC_LOCATIO FIELD FIELD FIELD
--------- ---------- ----- ----- -----
01-JAN-00 LOCATION1  A     A     A
01-JAN-01 LOCATION1  B     B     B
01-JAN-02 LOCATION1  C     C     C
01-JAN-03 LOCATION1  D     D     D
01-JAN-04 LOCATION1  E     E     E
01-JAN-00 LOCATION2  F     F     F
01-JAN-01 LOCATION2  G     G     G
01-JAN-00 LOCATION3  H     H     H
01-JAN-01 LOCATION3  I     I     I

9 rows selected.

SQL> SELECT c.* 
  2  FROM 
  3  csq_mc c,
  4  (SELECT mc_location, MAX(mc_date) max_date
  5   FROM csq_mc GROUP BY mc_location) m
  6  WHERE c.mc_location = m.mc_location
  7   AND  c.mc_date     = m.max_date;

MC_DATE   MC_LOCATIO FIELD FIELD FIELD
--------- ---------- ----- ----- -----
01-JAN-04 LOCATION1  E     E     E
01-JAN-01 LOCATION2  G     G     G
01-JAN-01 LOCATION3  I     I     I
 
very nice.

Thanks, djbjr.

It's sort of like creating a temp table, inserting the grouped records into the table, and then joining on the original table. However, I like how you don't have to go through all of the CREATE TABLE syntax associated with temp tables.

Is there a term for this type of query that you've given here?

Thanks,

Peter
 
In SQL Server or Sybase the code

SELECT mc_location, MAX(mc_date) max_date
5 FROM csq_mc GROUP BY mc_location) m

is a derived table. Derived table (m) is effectively like a temp table but only valid for the duration of query as opposed to temp tables that are valid for the whole session. In Oracle they are called in-line views.
 
Peter/DJBJr,

Not wanting to be nit-picky, just "nomenclaturly correct", for DJBJr's specific use, the technical term for the additional SELECT is an "in-line VIEW"; a sub-query, specifically, exists when the SELECT statement appears as an expression anywhere besides the FROM list.

[santa]Mufasa
(aka Dave of Sandy, Utah, USA)
[I can provide you with low-cost, remote Database Administration services: see our website and contact me via www.dasages.com]
 
Thanks Dave, I was answering with my Monday brain.

It is a in-line view.
 
and yes I know I should have said

an in-line view
 
[rofl][2thumbsup]

[santa]Mufasa
(aka Dave of Sandy, Utah, USA)
[I can provide you with low-cost, remote Database Administration services: see our website and contact me via www.dasages.com]
 
And the more general case - select top N records for each group( e.g for N =3)

select t1.mc_date,t1.mc_location,t1.field1,t1.field2,t1.field3
from
(
select mc_date,mc_location,field1,field2,field3,
dense_rank() over(partition by mc_location order by mc_location,mc_date desc) rnk
from csq_mc) t1
where t1.rnk <= 3 <- substitute your N value here

/

MC_DATE MC_LOCATIO FIELD FIELD FIELD
--------- ---------- ----- ----- -----
01-JAN-04 LOCATION1 E E E
01-JAN-03 LOCATION1 D D D
01-JAN-02 LOCATION1 C C C
01-JAN-01 LOCATION2 G G G
01-JAN-00 LOCATION2 F F F
01-JAN-01 LOCATION3 I I I
01-JAN-00 LOCATION3 H H H




 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top