I’m trying to return a sorted list of entries by their date, but keep matching columns together.
For a super simplified example, the table food is as follows.
id | name | group_uuid | date |
---|---|---|---|
1 | Apple | 6d37ca | 2023-05-20 |
2 | Cucumber | d90ad2 | 2023-05-20 |
3 | Orange | 6d37ca | 2023-06-14 |
4 | Carrot | d90ad2 | 2023-05-20 |
5 | Walnut | 03a7f3 | 2023-06-14 |
6 | Pecan | 03a7f3 | 2023-06-14 |
Is there a way to produce a result where the Orange comes directly after Apple, but not ordering by group_uuid alphabetically? I’d want to keep the group 6d37ca
at the top since its first entry has an id
of 1
.
If I use SELECT * FROM food ORDER BY date ASC, type, id ASC
it’ll produce the following result:
id | name | group_uuid | date |
---|---|---|---|
1 | Apple | 6d37ca | 2023-05-20 |
2 | Cucumber | d90ad2 | 2023-05-20 |
4 | Carrot | vegetable | 2023-05-20 |
3 | Orange | d90ad2 | 2023-06-14 |
5 | Walnut | 03a7f3 | 2023-06-14 |
6 | Pecan | 03a7f3 | 2023-06-14 |
I’d ideally want the result to look like this:
id | name | group_uuid | date |
---|---|---|---|
1 | Apple | 6d37ca | 2023-05-20 |
3 | Orange | 6d37ca | 2023-06-14 |
2 | Cucumber | d90ad2 | 2023-05-20 |
4 | Carrot | d90ad2 | 2023-05-20 |
5 | Walnut | 03a7f3 | 2023-06-14 |
6 | Pecan | 03a7f3 | 2023-06-14 |
Not sure if it’s possible or not, but any help would be appreciated.
2
Answers
You will need a subquery to get the group and minimum id of the group, and thus defined combine the group with the main query to then sort by the minemo id of the subquery.
Edit: after 47 tests lol sqlfinddle o/
Exemple:
And the resulting query:
Resulting:
OK full answer extracted from my previous comments:
Just putting
Apple
in first position andOrange
is second is straightforward enough. You use aCASE WHEN
statement to order your elements according to your arbitrary desire (Apple
is0
,Orange
is1
, everything else is2
) then further refine the order for all other elements as needed:note that the
ASC
there are superfluous as they are the default in most cases.However you mentioned you ‘want to keep the group
6d37ca
at the top’, and your desired result indicates you’re actually shooting for ordered groups, with each group’s position being decided by their member with the lowestID
. The first step is to get that lowestID
, which is done using theGROUP BY
statement and theMIN()
aggregate function:You then need to join this to your entire table, so each row in food "learns of" the lowest
ID
of the group they belong to:T1
here is an ALIAS, that is necessary to identify the temporary table created by our sub-query. It also allows us to differenciate between the twogroup_uuid
columns we have to handle during theJOIN
(this can also be done by giving an alias to thegroup_uuid
column!).Now, you don’t need to have
group_uuid
twice, and thegroup_min_id
, while necessary to order your results, is not part of it either, so we’ll just selectfood.*
(instead of the entire*
), and add the ordering statement. Note that we do not order overgroup_uuid
, sincegroup_min_id
already handles this part: