How to perform grouped ranking in MySQL
SELECT id_student, id_class, grade,
@student:=CASE WHEN @class <> id_class THEN 0 ELSE @student+1 END AS rn,
@class:=id_class AS clset
FROM
(SELECT @student:= -1) s,
(SELECT @class:= -1) c,
(SELECT *
FROM mytable
ORDER BY id_class, id_student
) t
This works in a very plain way:
- Initial query is ordered by
id_class
first,id_student
second. @student
and@class
are initialized to-1
@class
is used to test if the next set is entered. If the previous value of theid_class
(which is stored in@class
) is not equal to the current value (which is stored inid_class
), the@student
is zeroed. Otherwise is is incremented.@class
is assigned with the new value ofid_class
, and it will be used in test on step 3 at the next row.
Mysql Ranking within grouped results
You're almost there, use another variable to compute group:
SELECT @ss := CASE WHEN @grp = sem_id THEN @ss + 1 ELSE 1 END AS rank, sem_id, result_month, @grp := sem_id
FROM (select * from xx_table ORDER BY sem_id, result_month DESC) m
CROSS JOIN (SELECT @ss := 0, @grp = null) ss
See demo here.
SQL Rank Function with Group
Use a subquery for the aggregation and ordering:
SELECT id, sum_points, @rank := @rank + 1 AS rank
FROM (SELECT g.id, SUM(s.points) AS sum_points
FROM groups g LEFT JOIN
user_group ug
ON g.id = ug.clan LEFT JOIN
stats s
ON ug.user = s.id
GROUP BY g.id
ORDER BY sum_points DESC
) s CROSS JOIN
(SELECT @rank := 0) params;
This has been an issue in MySQL for a while -- variables don't work well with aggregation and ordering.
Note that in MySQL 8+, this is much more simply written as:
SELECT g.id, SUM(s.points) AS sum_points,
ROW_NUMBER() OVER (ORDER BY SUM(s.points) DESC) as rank
FROM groups g LEFT JOIN
user_group ug
ON g.id = ug.clan LEFT JOIN
stats s
ON ug.user = s.id
GROUP BY g.id
Mysql Group By Levels ranking
Finally got the desired result, ending up with the query, in order to get proper ranking for level wise:
SELECT m.rank,m.scorer AS points,m.player_id, m.quiz_id FROM (
SELECT d.player_id,d.scorer,
@rownum:= CASE WHEN @quiz_id <> d.quiz_id THEN 1 ELSE @rownum+1 END as rank,
@quiz_id:= d.quiz_id as quiz_id FROM
(SELECT @rownum := 1) r,
(SELECT @quiz_id := 0) c,(
SELECT t.player_id,SUM(t.score) as scorer, t.quiz_id
FROM answers t JOIN profile ON
profile.player_id = t.player_id
JOIN quiz ON t.quiz_id = quiz.id
WHERE t.is_active = 1 AND quiz.contest_id = 2 AND
profile.signin_source_id != 1 AND profile.is_active = 1
GROUP BY t.player_id,t.quiz_id
ORDER BY quiz_id DESC,scorer DESC, t.created_utc ASC) d
) m
WHERE m.scorer > 0 ORDER BY quiz_id
This will give the entire result set for all the levels for a specific group, if want to get the rank for specific levels from a specific group, then do add
AND t.quiz_id IN (1,2)
Thanks to all who ever participated!
mysql get ranking position grouped with joined table
You want rank()
or row_number()
:
select p.*,
rank() over (partition by player_game_id order by player_score desc) as rank
from players
order by player_game_id, player_score desc;
If two players have the same score, then rank()
gives them the same ranking. row_number()
will arbitrarily assign them adjacent rankings.
The above works on MySQL 8+. In earlier versions you have two options -- subqueries and variables. Here is an example using a correlated subquery:
select p.*,
(select 1 + count(*)
from players p2
where p2.player_game_id = p.player_game_id and
p2.player_score > p.player_score
) as ranking
from players
order by player_game_id, player_score desc;
This is not as efficient as rank()
. But with an index on players(player_game_id, player_score)
and not too many players per game, then this should have reasonable performance.
MySQL ranking with GROUP BY and SUM
Reminding the OP's question:
I would like to be able to get the rank of a given user_id.
In order to actually perform operations over the @rank
you have to user another derived table (yes, it is inefficient, that's why it is better not to handle this in MySQL):
SELECT * FROM (
SELECT s.*, @rank := @rank + 1 rank FROM (
SELECT user_id, sum(points) TotalPoints FROM t
GROUP BY user_id
) s, (SELECT @rank := 0) init
ORDER BY TotalPoints DESC
) r
WHERE user_id = 3
Output
| USER_ID | TOTALPOINTS | RANK |
|---------|-------------|------|
| 3 | 25 | 2 |
The process is basically:
- Get the total amounts of points per user
- Sort by those total points ranking
- Filter once you have the rank (otherwise, the rank will be compromised)
Fiddle here.
Group and Rank Rows in Mysql
Thanks for your help guys.
I was able to come up with an answer based on the following Query:
$totalQuery = "SELECT SUM(track_length) as usertracklength, username, MAX(track_create_time) as lasttrack, count(DISTINCT track_create_time) as totaldays FROM user_tracks GROUP BY username ORDER BY usertracklength DESC";
$totalResult = mysql_query($totalQuery);
$rankResult = mysql_query($totalQuery);
$totalNumEntries = mysql_num_rows($totalResult);
Then Ouputting that to an array
// rank position array
$rankArray = array();
while ($row1 = mysql_fetch_array($rankResult)) {
$rankArray[] = $row1['username'];
}
Then finding position of that username in the array by using a foreach in php
foreach ($rankArray as $rank => $user) {
if ($user == $username) {
$yourRank = $rank+1;
}
}
It's the long way around, but I suppose it works for what I'm going for.
Was kind of hoping to get it done within the mysql query for efficiency.
Thanks!
Related Topics
How to Implement One-To-One, One-To-Many and Many-To-Many Relationships While Designing Tables
Simple Way to Calculate Median With MySQL
Referring to a Column Alias in a Where Clause
How to Import an SQL File Using the Command Line in MySQL
Should I Use != or ≪≫ for Not Equal in T-Sql
How to Reset a Sequence in Oracle
Selecting With Multiple Where Conditions on Same Column
Dynamic Alternative to Pivot With Case and Group By
Select First Row of Every Group in Sql
Optimal Way to Concatenate/Aggregate Strings
How to See What Character Set a MySQL Database/Table/Column Is
How to Use Returning With on Conflict in Postgresql
How to Make SQL Case Sensitive String Comparison on MySQL
Will Ansi Join Vs. Non-Ansi Join Queries Perform Differently
Can't Connect to MySQL Server Error 111
MySQL Fails On: MySQL "Error 1524 (Hy000): Plugin 'Auth_Socket' Is Not Loaded"