MySQL - 如何确定按两列排序并允许绑定的表的位置排名?

问题描述 投票:0回答:3

我有一个桌子(锦标赛),其中包含一个球队列表及其积分和目标差异(进球得分 - 失球)。

比赛

+-----------+--------+-----------+
|   team    | points | goal_diff |
+-----------+--------+-----------+
| USA       |      7 |   -2      |
| Brazil    |     12 |   +7      |
| Argentina |     12 |   +10     |
| Germany   |      7 |   -2      |
| Italy     |      3 |    0      |
+-----------+--------+-----------+

我如何按分数排名,然后按目标差异保持与同一排名的关系并跳过后续的排名位置?我正在寻找查询以产生这个最终结果:

+-----------+--------+-----------+------+
|   team    | points | goal_diff | rank |
+-----------+--------+-----------+------+
| Argentina |     12 | +10       |    1 |
| Brazil    |     12 | +7        |    2 |
| USA       |      7 | -2        |    3 |
| Germany   |      7 | -2        |    3 |
| Italy     |      3 | 0         |    5 |
+-----------+--------+-----------+------+

我已经能够对它们进行排名并通过点列保持联系相同,但不知道如何处理第二列条件

SELECT s.team, s.points, s.goal_diff,
    (( SELECT COUNT(DISTINCT points) FROM Tournament WHERE points > s.points ) + 1) AS rank
FROM Tournament s
ORDER BY s.points DESC

谢谢您的帮助!

mysql
3个回答
1
投票

对于任何想要解决这个问题的人,我最终将我的数据库升级到MariaDB 10.3.14并使用了RANK()函数,它完全符合我的需要。

这是代码:

SELECT team, points, goal_diff,
    RANK() OVER (
        ORDER BY
            points DESC,
            goal_diff DESC
        ) rank
FROM Tournament;

我知道升级数据库可能不是每个人的选择,但在我的情况下这是一个非常简单的解决方案。希望它对其他人也有帮助。


1
投票

我错过了:在#1(在@rank之后),这就是为什么要显示blob和null值的原因

SELECT
    a.team,
    a.points,
    a.goal_diff,
    a.rank 
FROM
    (
    SELECT
        t.team,
        t.points,
        t.goal_diff,
    IF
        ( @points = t.points, 
        IF 
            (@goal_diff = t.goal_diff, @rank, @rank :=@inRank),
        @rank := @inRank ) AS rank,                               # 2
        @inRank := @inRank + 1,                                   # 3
        @points := t.points,                                      # 4
        @goal_diff := t.goal_diff  
    FROM
        `tournament` t,
        ( SELECT @points := NULL, @goal_diff := NULL, @rank := 0, @inRank := 1 ) b  # 1
    ORDER BY
    t.points DESC, t.goal_diff DESC
    ) a

说明:

@用于声明变量。 :=表示为变量赋值。 #1 sql实际上是一个变量initial。

@points :  a custom declared variable for storing the points value in last row
@rank   :  a custom declared variable for storing regular condition rank number  
@inRank :  a custom declared variable for storing a count of row

mysql中的if(boolean,trueResult,falseResult)函数有点像三元运算。在#2中,如果初始变量@points等于所选的值,它将显示@Rank的值,现在为0。这个if()函数用于判断点值是否相同。

在if()函数之后,我们在#3和#4中分配变量。

sql#3在每一行都会增加,这个变量会计算行号。因此,当积分不相同时,我可以获得等级。我认为将@inRank重命名为@increaseRank会更好。

sql#4将此行的points值赋给变量。我们用它来与下一行的分值进行比较。


0
投票

所以,基本上,这是来自@ wl.GIG答案的次要编辑。运行@ wl.GIG时得到的结果如下;

+-------------+----------+-------------+--------+
|    team     |  points  |  goal_diff  |  rank  |
+-------------+----------+-------------+--------+
|  Brazil     |      12  |          7  |     1  |
|  Argentina  |      12  |         10  |     1  |
|  USA        |       7  |         -2  |     3  |
|  Germany    |       7  |         -2  |     3  |
|  Italy      |       3  |          0  |     5  |
+-------------+----------+-------------+--------+ 

它没有给出OP所需的正确等级,但这是一个非常好的方法,我对它非常感兴趣。所以,我已经根据OP的要求进行了可以返回排名的测试,这是我提出的:

SELECT
    a.team,
    a.points,
    a.goal_diff,
    a.rank 
FROM (SELECT
        t.team,
        t.points,
        t.points+t.goal_diff AS tp, -- I've added this.
        t.goal_diff,
     IF
        (@points = t.points+t.goal_diff, --- changed this part.
        @rank, @rank := @inRank) AS rank,
        @inRank := @inRank + 1,
        @Points := t.points+t.goal_diff --- and changed this part.
    FROM
        `tournament` t,
        ( SELECT @points := NULL, @rank = 0, @inRank := 1 ) b 
        ORDER BY t.points DESC,t.goal_diff DESC 
        -- and added another condition in the ordering
        ) a;

正如你所看到的,这不是一个很大的编辑,但我用这个,我得到如下结果:

+-------------+----------+-------------+--------+
|    team     |  points  |  goal_diff  |  rank  |
+-------------+----------+-------------+--------+
|  Argentina  |      12  |         10  |     1  |
|  Brazil     |      12  |          7  |     2  |
|  USA        |       7  |         -2  |     3  |
|  Germany    |       7  |         -2  |     3  |
|  Italy      |       3  |          0  |     5  |
+-------------+----------+-------------+--------+

而已。

© www.soinside.com 2019 - 2024. All rights reserved.