Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select the 3 most recent records where the values of one column are distinct

I have the following table:

    id       time      text      otheridentifier     -------------------------------------------     1        6         apple     4     2        7         orange    4     3        8         banana    3     4        9         pear      3     5        10        grape     2 

What I want to do is select the 3 most recent records (by time desc), whose otheridentifiers are distinct. So in this case, the result would be id's: 5, 4, and 2.

id = 3 would be skipped because there's a more recent record with the same otheridentifier field.

Here's what I tried to do:

SELECT * FROM `table` GROUP BY (`otheridentifier`) ORDER BY `time` DESC LIMIT 3 

However, I end up getting rows of id = 5, 3, and 1 instead of 5, 4, 2 as expected.

Can someone tell me why this query wouldn't return what I expected? I tried changing the ORDER BY to ASC but this simply rearranges the returned rows to 1, 3, 5.

like image 955
atp Avatar asked May 29 '09 05:05

atp


People also ask

How do I SELECT distinct in one column?

Adding the DISTINCT keyword to a SELECT query causes it to return only unique values for the specified column list so that duplicate rows are removed from the result set.

How can I get distinct values of all columns in SQL?

To get unique or distinct values of a column in MySQL Table, use the following SQL Query. SELECT DISTINCT(column_name) FROM your_table_name; You can select distinct values for one or more columns.

How do you SELECT distinct columns in join queries?

DISTINCT is for all the columns in the select clause, which means all columns combined will be used to get distinct rows. TOP X will only select the number of rows mentioned in X .


2 Answers

It doesn't return what you expect because grouping happens before ordering, as reflected by the position of the clauses in the SQL statement. You're unfortunately going to have to get fancier to get the rows you want. Try this:

SELECT * FROM `table` WHERE `id` = (     SELECT `id`     FROM `table` as `alt`     WHERE `alt`.`otheridentifier` = `table`.`otheridentifier`     ORDER BY `time` DESC     LIMIT 1 ) ORDER BY `time` DESC LIMIT 3 
like image 170
chaos Avatar answered Oct 04 '22 04:10

chaos


You could join the table on itself to filter the last entry per otheridentifier, and then take the top 3 rows of that:

SELECT last.* FROM `table` last LEFT JOIN `table` prev      ON prev.`otheridentifier` = last.`otheridentifier`     AND prev.`time` < last.`time` WHERE prev.`id` is null ORDER BY last.`time` DESC  LIMIT 3 
like image 25
Andomar Avatar answered Oct 04 '22 02:10

Andomar