简体   繁体   中英

MySQL Order by date and grouping by name

Table

mysql> select * from temp;
+--------+---------------------+
| name   | created_at          |
+--------+---------------------+
| second | 2020-01-01 12:00:00 |
| first  | 2020-01-01 12:10:00 |
| second | 2020-01-01 12:20:00 |
| third  | 2020-01-01 12:30:00 |
| third  | 2020-01-01 12:40:00 |
| first  | 2020-01-01 12:50:00 |
+--------+---------------------+

In the above example, I want to order by created_at first and show rows with the same name.

So I trying to ordering with created_at, name.

mysql> select * from temp order by created_at, name;
+--------+---------------------+
| name   | created_at          |
+--------+---------------------+
| second | 2020-01-01 12:00:00 |
| first  | 2020-01-01 12:10:00 |
| second | 2020-01-01 12:20:00 |
| third  | 2020-01-01 12:30:00 |
| third  | 2020-01-01 12:40:00 |
| first  | 2020-01-01 12:50:00 |
+--------+---------------------+

But it does not grouping name.

After searched about order by, I found that in the case of the second column, it is applied only to the result of the first order by.

Desired result

+--------+---------------------+
| name   | created_at          |
+--------+---------------------+
| second | 2020-01-01 12:00:00 |
| second | 2020-01-01 12:20:00 |
| first  | 2020-01-01 12:10:00 |
| first  | 2020-01-01 12:50:00 |
| third  | 2020-01-01 12:30:00 |
| third  | 2020-01-01 12:40:00 |
+--------+---------------------+

How can I manipulate query to achieve it?

You have to order by minimum created_at of every named group first then order by created_at .

SELECT name, created_at
FROM TEMP tem
ORDER BY
    (SELECT MIN(tem2.created_at)
     FROM TEMP tem2 
     WHERE tem.name = tem2.name), created_at

Bellow part will get minimum created_at for name group of every row's name

SELECT MIN(tem2.created_at)
         FROM TEMP tem2 
         WHERE tem.name = tem2.name

Now every group is ordered by the group's minimum created_at and then order every group name's by created_at .

You could join this table with a subquery of the minimal created_at per name, and order by that:

SELECT   t.name, created_at
FROM     mytable t
JOIN     (SELECT   name, MIN(created_at) AS min_created_at
          FROM     mytable
          GROUP BY name) m ON t.name = m.name
ORDER BY min_created_at, t.name, t.created_at

If you are running MySQL 8.0, you can just use window min() for ordering:

select *
from temp
order by 
    min(created_at) over(partition by name), 
    created_at

The window min() gives you the minimum created_at across all records that have th same name .

In earlier versions, I would use a correlated subquery directly in the order by clause:

select *
from temp t
order by
    (select min(t1.created_at) from temp t1 where t1.name = t.name),
    created_at

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM