(Reprinted) Implementing Advanced Ranking Function of Rank in MySQL

Reprinted: Link: http://fellowtuts.com/mysql/query-to-obtain-rank-function-in-mysql/
Disclaimer: If I violate anyone's rights, please contact me and I will delete it.
Welcome experts to spray I


There is no Rank ranking function in MySQL. When we need to query the ranking, we can only use the basic query statement in the MySQL database to query the general ranking. Nevertheless, don't underestimate the basic and simple query statement, we can use it to achieve the same advanced ranking effect as the Rank function.

Here I use a simple example to implement the ranking query:

First, we first create a players table that we need to perform advanced ranking queries.

CREATE TABLE `players` (
  `pid` int(2) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `age` int(2) NOT NULL,
  PRIMARY KEY (`pid`),
  UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

INSERT INTO `players` (`pid`, `name`, `age`) VALUES
(1, 'Samual', 25),
(2, 'Vino', 20),
(3, 'John', 20),
(4, 'Andy', 22),
(5, 'Brian', 21),
(6, 'Dew', 24),
(7, 'Kris', 25),
(8, 'William', 26),
(9, 'George', 23),
(10, 'Peter', 19),
(11, 'Tom', 20),
(12, 'Andre', 20);

1. Implement Rank ordinary ranking function in MySQL

Here, we want to get a column of the ranking field and the ascending order of age. So our query statement will be:


SELECT pid, name, age, @curRank := @curRank + 1 AS rank
FROM players p, (
SELECT @curRank := 0
) q
ORDER BY age

Output:

| PID |    NAME | AGE | RANK |
|-----|---------|-----|------|
|  10 |   Peter |  19 |    1 |
|  12 |   Andre |  20 |    2 |
|   2 |    Vino |  20 |    3 |
|   3 |    John |  20 |    4 |
|  11 |     Tom |  20 |    5 |
|   5 |   Brian |  21 |    6 |
|   4 |    Andy |  22 |    7 |
|   9 |  George |  23 |    8 |
|   6 |     Dew |  24 |    9 |
|   7 |    Kris |  25 |   10 |
|   1 |  Samual |  25 |   11 |
|   8 | William |  26 |   12 |

To declare a variable in mysql, you must use the @ symbol before the variable name. The (@curRank := 0) part of the FROM clause allows us to initialize variables without the need for a separate SET command. Of course, SET can also be used, but it will handle two queries:

SET @curRank := 0;
SELECT pid, name, age, @curRank := @curRank + 1 AS rank
FROM players
ORDER BY age

2. The query is sorted in descending order

Firstly, sort by age in descending order, and secondly by name, just modify the query statement and add ORDER BY, DESC and column name.

SELECT pid, name, age, @curRank := @curRank + 1 AS rank
FROM players p, (
SELECT @curRank := 0
) q
ORDER BY age DESC, name

Output:

| PID |    NAME | AGE | RANK |
|-----|---------|-----|------|
|   8 | William |  26 |    1 |
|   7 |    Kris |  25 |    2 |
|   1 |  Samual |  25 |    3 |
|   6 |     Dew |  24 |    4 |
|   9 |  George |  23 |    5 |
|   4 |    Andy |  22 |    6 |
|   5 |   Brian |  21 |    7 |
|  12 |   Andre |  20 |    8 |
|   3 |    John |  20 |    9 |
|  11 |     Tom |  20 |   10 |
|   2 |    Vino |  20 |   11 |
|  10 |   Peter |  19 |   12 |

3. Implement the rank general parallel ranking function in MySQL

Now, if we want to assign the same rank to the rows of parallel data, it means that those rows with the same value in the rank comparison column should maintain the same rank when calculating the rank in MySQL (for example, age in our example) . For this, we use an additional variable.

SELECT pid, name, age, 
CASE 
WHEN @prevRank = age THEN @curRank 
WHEN @prevRank := age THEN @curRank := @curRank + 1
END AS rank
FROM players p, 
(SELECT @curRank :=0, @prevRank := NULL) r
ORDER BY age

Output:

| PID |    NAME | AGE | RANK |
|-----|---------|-----|------|
|  10 |   Peter |  19 |    1 |
|  12 |   Andre |  20 |    2 |
|   2 |    Vino |  20 |    2 |
|   3 |    John |  20 |    2 |
|  11 |     Tom |  20 |    2 |
|   5 |   Brian |  21 |    3 |
|   4 |    Andy |  22 |    4 |
|   9 |  George |  23 |    5 |
|   6 |     Dew |  24 |    6 |
|   7 |    Kris |  25 |    7 |
|   1 |  Samual |  25 |    7 |
|   8 | William |  26 |    8 |

As shown above, two or more rows with the same data and ranking will all get the same ranking. Players Andre, Vino, John and Tom all have the same age, so they are tied for second place. The next highest age player (Brian) ranks third. This query is equivalent to the DENSE_RANK() function in MSSQL and ORACLE.

4. Implement Rank advanced parallel ranking function in MySQL

When using the RANK() function, if two or more rows are ranked side by side, the same row will have the same ranking, but there is a relative gap in the actual ranking.

SELECT pid, name, age, rank FROM
(SELECT pid, name, age,
@curRank := IF(@prevRank = age, @curRank, @incRank) AS rank, 
@incRank := @incRank + 1, 
@prevRank := age
FROM players p, (
SELECT @curRank :=0, @prevRank := NULL, @incRank := 1
) r 
ORDER BY age) s

This is a subquery in a query. When we use three variables (@incRank, @prevRank, @curRank) to calculate the relationship, in the query result, we have filled in the ranking gap caused by the tie. We have closed the subquery to the query. This query is equivalent to the RANK() function in MSSQL and ORACLE.

| PID |    NAME | AGE | RANK |
|-----|---------|-----|------|
|  10 |   Peter |  19 |    1 |
|  12 |   Andre |  20 |    2 |
|   2 |    Vino |  20 |    2 |
|   3 |    John |  20 |    2 |
|  11 |     Tom |  20 |    2 |
|   5 |   Brian |  21 |    6 |
|   4 |    Andy |  22 |    7 |
|   9 |  George |  23 |    8 |
|   6 |     Dew |  24 |    9 |
|   7 |    Kris |  25 |   10 |
|   1 |  Samual |  25 |   10 |
|   8 | William |  26 |   12 |

Here we can see that Andre, Vino, John and Tom all have the same age, so they are tied for second place. The next oldest player (Brian) is ranked 6th instead of 3rd, because 4 people are tied for 2nd.

Okay, I hope that after these examples, you can understand the difference between RANK() and DENSE_RANK(), and know where to use which query to get the rank function in MySQL. Thank you.

Reprint http://fellowtuts.com/mysql/query-to-obtain-rank-function-in-mysql

Guess you like

Origin blog.csdn.net/qq_45531729/article/details/112287722