Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL query to return only 1 record per group ID

I'm looking for a way to handle the following scenario. I have a database table that I need to return only one record for each "group id" that is contained within the table, furthermore the record that is selected within each group should be the oldest person in the household.

ID   Group ID   Name               Age 1   134        John Bowers        37 2   134        Kerri Bowers       33 3   135        John Bowers        44 4   135        Shannon Bowers     42 

So in the sample data provided above I would need ID 1 and 3 returned, as they are the oldest people within each group id.

This is being queried against a SQL Server 2005 database.

like image 945
Richard West Avatar asked Dec 23 '09 17:12

Richard West


People also ask

How do I return a single record in SQL?

To return only the first row that matches your SELECT query, you need to add the LIMIT clause to your SELECT statement. The LIMIT clause is used to control the number of rows returned by your query. When you add LIMIT 1 to the SELECT statement, then only one row will be returned.

How do you limit the number of records to return from a query?

The SQL SELECT LIMIT statement is used to retrieve records from one or more tables in a database and limit the number of records returned based on a limit value. TIP: SELECT LIMIT is not supported in all SQL databases. For databases such as SQL Server or MSAccess, use the SELECT TOP statement to limit your results.

How do you SELECT the first record in a GROUP BY SQL?

First, you need to write a CTE in which you assign a number to each row within each group. To do that, you can use the ROW_NUMBER() function. In OVER() , you specify the groups into which the rows should be divided ( PARTITION BY ) and the order in which the numbers should be assigned to the rows ( ORDER BY ).


2 Answers

SELECT  t.* FROM    (         SELECT  DISTINCT groupid         FROM    mytable         ) mo CROSS APPLY         (         SELECT  TOP 1 *         FROM    mytable mi         WHERE   mi.groupid = mo.groupid         ORDER BY                 age DESC         ) t 

or this:

SELECT  * FROM    (         SELECT  *, ROW_NUMBER() OVER (PARTITION BY groupid ORDER BY age DESC) rn         FROM    mytable         ) x WHERE   x.rn = 1 

This will return at most one record per group even in case of ties.

See this article in my blog for performance comparisons of both methods:

  • SQL Server: Selecting records holding group-wise maximum
like image 147
Quassnoi Avatar answered Sep 21 '22 17:09

Quassnoi


Use:

SELECT DISTINCT        t.groupid,        t.name   FROM TABLE t   JOIN (SELECT t.groupid,                MAX(t.age) 'max_age'           FROM TABLE t       GROUP BY t.groupid) x ON x.groupid = t.groupid                            AND x.max_age = t.age 

So what if there's 2+ people with the same age for a group? It'd be better to store the birthdate rather than age - you can always calculate the age for presentation.

like image 20
OMG Ponies Avatar answered Sep 20 '22 17:09

OMG Ponies