Reputation: 1171
I am learning SQL.
I have these records in my table:
STUDENT_NAME STATUS CLASS_ID ORDERING
----------------------------------------------
Adam 'FR' 10 1
Conan 'SE' 3 5
Chris 'SE' 4 8
Louis 'JR' null 10
Dave 'JR' 14 17
Alice 'SO' 14 8
Paul 'SE' 4 6
Tom 'SO' null 3
Eric 'FR' 14 5
Blake 'JR' 11 2
Ryan 'SE' 3 13
Matt 'FR' null 22
And I want to order by ORDERING, but I want to group by its STATUS (like the value which has same status be together).
For example, the result would look like this:
STUDENT_NAME STATUS CLASS_ID ORDERING
----------------------------------------------
Adam 'FR' 10 1
Eric 'FR' 14 5
Matt 'FR' null 22
Blake 'JR' 11 2
Louis 'JR' null 10
Dave 'JR' 14 17
Tom 'SO' null 3
Alice 'SO' 14 8
Conan 'SE' 3 5 // SAME CLASS_ID
Ryan 'SE' 3 13
Paul 'SE' 4 6 // SAME CLASS_ID
Chris 'SE' 4 8
Adam has lowest ORDERING value, so he goes the top. But his STATUS is 'FR', so the next student will be Eric who has lower ORDERING than Matt.
EXTRA CONDITION: If CLASS_ID is not null, I want to group it based on CLASS_ID
Is it even possible to get the result with the clause 'SELECT'...'ORDER BY'? (Please say yes!)
I use this query, but it doesn't work well:
SELECT ... FROM STUDENTS stu
ORDER BY
(SELECT MIN(S.ORDERING) FROM STUDENTS S WHERE S.STATUS = 'FR' AND stu.STATUS = 'FR'),
(SELECT MIN(S.CLASS_ID) FROM STUDENTS S WHERE S.CLASS_ID = stu.CLASS_ID),
stu.CLASS_ID ASC,
stu.ORDERING ASC
I could use the CASE clause too. I need your help!
Upvotes: 0
Views: 75
Reputation: 32392
It sounds like you want to order by the minimum of each group
select s.* from students s
join (
select status, min(ordering) min_status_ordering
from students group by status
) t1 on t1.status = s.status
join (
select class_id, status, min(ordering) min_class_ordering
from students group by status, class_id
) t2 on (t2.class_id = s.class_id
or (t2.class_id is null and s.class_id is null))
and t2.status = s.status
order by t1.min_status_ordering, t2.min_class_ordering, s.ordering, s.status, s.class_id
http://sqlfiddle.com/#!2/f4eb4/2
Upvotes: 1
Reputation: 6663
Try this. I wrote this for MySQL, it may work for SQL Server also. It will group NULL CLASS_IDS together (if there are any). I don't can't think of another way to do it. It gives the results you are looking for.
SELECT stu.*
FROM STUDENTS stu
ORDER BY
(SELECT MIN(S.ORDERING) FROM STUDENTS S WHERE S.STATUS = stu.STATUS),
(SELECT MIN(S.ORDERING) FROM STUDENTS S WHERE S.STATUS = stu.STATUS AND IFNULL(S.CLASS_ID, '') = IFNULL(stu.CLASS_ID, '')),
stu.ORDERING
SQL Fiddle: sqlfiddle.com/#!2/a5a10/10/0
Upvotes: 2