Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ORDER BY and GROUP BY together

My table looks like this (and I'm using MySQL):

m_id | v_id | timestamp ------------------------ 6    |   1  | 1333635317 34   |   1  | 1333635323 34   |   1  | 1333635336 6    |   1  | 1333635343 6    |   1  | 1333635349 

My target is to take each m_id one time, and order by the highest timestamp.

The result should be:

m_id | v_id | timestamp ------------------------ 6    |   1  | 1333635349 34   |   1  | 1333635336 

And i wrote this query:

SELECT * FROM table GROUP BY m_id ORDER BY timestamp DESC 

But, the results are:

m_id | v_id | timestamp ------------------------ 34   |   1  | 1333635323 6    |   1  | 1333635317 

I think it causes because it first does GROUP_BY and then ORDER the results.

Any ideas? Thank you.

like image 940
Luis Avatar asked Apr 05 '12 14:04

Luis


People also ask

Which comes first ORDER BY or GROUP BY?

In the query, GROUP BY clause is placed before ORDER BY clause if used any.

Can we use ORDER BY clause along with the GROUP BY clause?

The ORDER BY clause, like the GROUP BY clause, could be used in conjunction with the SELECT statement. ASC denotes ascending order, while DESC denotes descending order. The following is the syntax to use the ORDER BY clause in a SQL statement: SELECT expressions.

Can you do ORDER BY and GROUP BY in SQL?

Order By and Group By Clause in SQLGroup By in SQL is used to arrange similar data into groups and Order By in SQL is used to sort the data in ascending or descending order.

Does ORDER BY affect GROUP BY?

No, the order doesn't matter for the GROUP BY clause. MySQL and SQLite are the only databases I'm aware of that allow you to select columns which are omitted from the group by (non-standard, not portable) but the order doesn't matter there either. Save this answer.


2 Answers

One way to do this that correctly uses group by:

select l.*  from table l inner join (   select      m_id, max(timestamp) as latest    from table    group by m_id ) r   on l.timestamp = r.latest and l.m_id = r.m_id order by timestamp desc 

How this works:

  • selects the latest timestamp for each distinct m_id in the subquery
  • only selects rows from table that match a row from the subquery (this operation -- where a join is performed, but no columns are selected from the second table, it's just used as a filter -- is known as a "semijoin" in case you were curious)
  • orders the rows
like image 50
Matt Fenwick Avatar answered Sep 21 '22 11:09

Matt Fenwick


If you really don't care about which timestamp you'll get and your v_id is always the same for a given m_i you can do the following:

select m_id, v_id, max(timestamp) from table group by m_id, v_id order by max(timestamp) desc 

Now, if the v_id changes for a given m_id then you should do the following

select t1.* from table t1 left join table t2 on t1.m_id = t2.m_id and t1.timestamp < t2.timestamp where t2.timestamp is null order by t1.timestamp desc 
like image 28
Mosty Mostacho Avatar answered Sep 24 '22 11:09

Mosty Mostacho