users:
user_id user_name
---------------------
1 User A
2 User B
tracking:
user_id track
---------------------
1 no
2 no
applications:
user_id date_of_application date_ended grade status
---------------------------------------------------------------
1 2011-01-01 2011-02-28 1.0 Ended
1 2011-02-02 2011-03-28 1.0 Ended
1 2011-03-03 2011-04-28 (1.5) Ended
2 2011-01-01 2011-02-20 2.0 Ended
2 2011-02-02 2011-03-11 2.5 Ended
2 2011-03-03 2011-04-28 (1.0) Ended
1 2011-05-10 - - Pending
2 2011-05-15 - - Pending
- note that the table can contain multiple records of the same user as long as all its previous applications have ended (status = ended)
- user_id is not unique (applies to the applications table only)
- date is in yy-mm-dd format
- date_ended and grade are only updated the instant the application has ended
- also, I understand that it probably is recommended for ‘status’ to have its own table, however I would prefer that the above tables are taken as is (minus the typos and significant errors of course)
What I want to accomplish here is to retrieve all rows WHERE status is ‘Pending’ and such that the value for the grade column for each of these retrieved rows is the value of the latest grade (in other words the row with the latest date_ended), (in parenthesis above) where status is ‘Ended’ for this particular user (or row).
Also, I would need to have the first 10 rows of the result to be ORDERed BY grade ASC. And have the succeeding rows after that (11th row up to the final row) to be ORDERed BY date_of_application ASC.
Clearly SQL queries isn’t my strongest area so I’m not sure if it’s better (or is only possible) to perform those ORDER BY(s) using 2 or more queries. I however prefer this to be done using a single query only.
The desired result:
user_id user_name date_of_application grade status track
--------------------------------------------------------------------
1 User A 2011-05-10 (1.5) Pending no
2 User B 2011-05-15 (1.0) Pending no
Working code I have so far on my end [minus the possible typos], (and listed are additions to be applied):
- latest grade
- ORDER BY grade (first 10), ORDER BY date_of_application (11th up to last row)
Query:
SELECT users.user_name,
t.track,
a.user_id,
a.date_of_application,
a.status,
(SELECT ae.grade
FROM applications AS ae
WHERE ae.status = 'Ended'
AND ae.user_id = a.user_id
LIMIT 1) AS grade
FROM users
JOIN applications AS a ON users.user_id = a.user_id
JOIN tracking AS t ON users.user_id = t.user_id
WHERE a.status = 'Pending'
ORDER BY grade ASC
You probably trying to do too much in one query here.
Anyway, if you want something to hurt your eyes:
This does make the following assumptions:
usersandtrackingtableEDIT
To explain this query a bit:
Inline view aliased
a(aka ‘The Top Half’) brings back a list of the top 10 users according to their most recent ‘ended’ grade ascending. Note the following part of the query that strips any brackets from the grade, converts the resulting number to a decimal to 2 decimal places and orders them ascending by grade and then, in case of equal grade scores, by user_id:Inline view
bis pretty much the same as inline viewaexcept that excludes users that would appear in The Top Half and orders the results by statusDESC(to move those users with no applications to the bottom of the list) and date of applicationASC.