Search code examples
mysqlrankingdense-rank

Simulate rank in mysql (without rank) with two conditions


Coming from this answer: Rank based on two columns

I've the following example:

CREATE TABLE tmpPoradi 
    (`player` int, `wins` int, `diff` int)
;

INSERT INTO tmpPoradi 
    (`player`, `wins`, `diff`)
VALUES
    (1, 10, 12),
    (2, 8, 2),
    (3, 10, 10),
    (4, 8, 1),
    (5, 8, 7),
    (6, 10, 14),
    (8, 10, 10),
   (7, 12, 3)
;

and the desired result must be:

+--------+------+------+------+
| player | wins | diff | rank |
+--------+------+------+------+
|      7 |   12 |    3 |    1 |
|      6 |   10 |   14 |    2 |
|      1 |   10 |   12 |    3 |
|      3 |   10 |   10 |    4 |
|      8 |   10 |   10 |    4 |
|      5 |    8 |    7 |    5 |
|      2 |    8 |    2 |    6 |
|      4 |    8 |    1 |    7 |
+--------+------+------+------+

The thing is that the original answer returns the row count:

 SELECT player, wins, diff,rank from
 (
 SELECT player, wins, diff, @winrank := @winrank + 1 AS rank
 from tmpPoradi,(SELECT @winrank := 0) r 
 ORDER BY wins DESC,diff DESC
 )  rt
ORDER BY rank 

returns:

+---------+-------+-------+-------+
|  player |  wins |  diff |  rank |
+---------+-------+-------+-------+
|       7 |    12 |     3 |     1 |
|       6 |    10 |    14 |     2 |
|       1 |    10 |    12 |     3 |
|       3 |    10 |    10 |     4 |
|       8 |    10 |    10 |     5 |
|       5 |     8 |     7 |     6 |
|       2 |     8 |     2 |     7 |
|       4 |     8 |     1 |     8 |
+---------+-------+-------+-------+

and my attemp with conditions returns the following result: (dont know why)

  SELECT player, wins, diff,rank from
 (
 SELECT player, wins, diff, @winrank := IF(wins = diff,@winrank,@winrank + 1) AS rank
 from tmpPoradi,(SELECT @winrank := 0) r 
 ORDER BY wins DESC,diff DESC
 )  rt
ORDER BY rank 


+---------+-------+-------+-------+
|  player |  wins |  diff |  rank |
+---------+-------+-------+-------+
|       7 |    12 |     3 |     1 |
|       6 |    10 |    14 |     2 |
|       3 |    10 |    10 |     3 |
|       8 |    10 |    10 |     3 |
|       1 |    10 |    12 |     3 |
|       5 |     8 |     7 |     4 |
|       2 |     8 |     2 |     5 |
|       4 |     8 |     1 |     6 |
+---------+-------+-------+-------+

so the question is:

What I'm doing wrong and how can achieve rank by wins and then if wins are tied, subrank by diff, and then if diff are tied, rank are the same?


Solution

  • SQL DEMO

      SELECT player, wins, diff, dense_rank, rank, dense_val, prev_wins, prev_diff
      FROM
         (
             SELECT player, 
                    wins,                 
                    diff, 
                    @dense_rank := IF(wins = @prev_wins and diff = @prev_diff, @dense_rank, @dense_rank + @dense_val ) AS dense_rank,                
                    @dense_val  := IF(wins = @prev_wins and diff = @prev_diff, @dense_val + 1 , 1) as dense_val,
                    @rank := @rank + 1 as rank,
                    @prev_wins := wins as prev_wins,
                    @prev_diff := diff as prev_diff
    
             FROM tmpPoradi,(SELECT @dense_rank := 0, @dense_val := 1, @rank := 0, @prev_wins := 0, @prev_diff := 0) r 
             ORDER BY wins DESC,diff DESC
         )  rt
      ORDER BY rank 
    

    OUTPUT

    enter image description here