Another common request is to rank records, or a subset of records, against each other. Think of sports box scores, top ten lists or consumer product rankings. Take this example table:
tblScore:
CompID - Long (PK)
PlayerID - Long
Score - Long
CompID PlayerID Score
1 1 39
1 2 38
1 3 32
2 1 41
2 2 39
2 3 41
3 1 42
3 2 41
3 3 43
4 1 39
4 2 33
4 3 42
5 1 44
5 2 42
5 3 28
6 1 39
6 2 42
6 3 47
Typically some subset of records needs to be defined (e.g. CompID = 6) and then a sequential number needs to be generated to indicate ranking. A sub-query is used to count the number of records that meet or exceed the current record’s Score value and this becomes the ranking. This sub-query becomes a correlated sub-query because of the need to only count scores for our subset of records and and to count records that meet criteria found in the outer query:
SELECT
tblScores.PlayerID
, tblScores.Score
, (SELECT Count(*) FROM tblScores As S WHERE S.CompID = 6 AND S.Score >= tblScores.Score) AS Rank
FROM tblScores
WHERE (((tblScores.CompID)=6))
ORDER BY tblScores.Score DESC;
And the results look like this:
PlayerID Score Rank
3 47 1
2 42 2
1 39 3
Additionally it may be desirable to calculate a “behind” value. This query generates that value:
SELECT
tblScores.PlayerID
, tblScores.Score
, IIf( ((SELECT Max(Score) FROM tblScores WHERE CompID = 6) - tblScores.Score) = 0, "----"
, ((SELECT Max(Score) FROM tblScores WHERE CompID = 6) - tblScores.Score)) AS Behind
, (SELECT Count(*) FROM tblScores As S WHERE S.CompID = 6 AND S.Score >= tblScores.Score) AS Rank
FROM tblScores
WHERE (((tblScores.CompID)=6))
ORDER BY tblScores.Score DESC;
and the results look like this:
PlayerID Score Behind Rank
3 47 ---- 1
2 42 5 2
1 39 8 3
See a more advanced version of ranking – only within a group further down the page.