MySQL 查找排名前 3 的团队

Posted

技术标签:

【中文标题】MySQL 查找排名前 3 的团队【英文标题】:MySQL Find Top 3 Ranked Teams 【发布时间】:2016-10-15 15:57:17 【问题描述】:

我需要通过以下方式在我的排名页面上显示列表

Team_Name      Played       Won      Lost     Points     In_Top_3
Some Team      5            5        0        11          Yes

积分计算方式为

2 分/比赛获胜

如果比赛获胜是四分之一决赛,则+1

如果比赛是半决赛获胜,则+2

+3 如果比赛获胜是大结局

我成功地实现了其中的大多数,但其中一个是 In_Top_3,尽管有一个便宜的解决方法来添加 $count 并检查它是否为 <=3 并在列下显示是,但我有什么办法可以做使用 SQL 查询。

我目前的SQL查询如下

SELECT
    T.id, T.name, T.status, IFNULL(T.image, 'no-image.png') AS DP,
    (SELECT COUNT(*)
    FROM badminton_matches MT
    WHERE (MT.team_one = T.id OR MT.team_two = T.id)) 
  AS played,
    (SELECT COUNT(*)
    FROM badminton_match_results R
    WHERE R.winner_id = T.id) AS won,
    (SELECT COUNT(*)
    FROM badminton_matches MT JOIN badminton_match_results MR
        ON (MR.match_id = MT.id)
    WHERE (MT.team_one = T.id OR MT.team_two = T.id) AND MR.winner_id != T.id) AS lost,
    (
   ((SELECT COUNT(*)
    FROM badminton_match_results R
    WHERE R.winner_id = T.id) * 2) 
     + 
   ((SELECT COUNT(*)
    FROM badminton_match_results R JOIN badminton_matches M ON (M.id = R.match_id AND M.match_type = 'quarter')
    WHERE R.winner_id = T.id))
  ) AS Points
FROM badminton_teams T
ORDER BY (Points) DESC

当我有以下表结构时,我如何标记排名前 3 的团队以及我当前的查询,并且

表格:团队

+------------+----------------------------+------+-----+-------------------+----------------+
| Field      | Type                       | Null | Key | Default           | Extra          |
+------------+----------------------------+------+-----+-------------------+----------------+
| id         | int(11)                    | NO   | PRI | NULL              | auto_increment |
| name       | varchar(150)               | NO   |     | NULL              |                |
| image      | text                       | YES  |     | NULL              |                |
| status     | enum('active','in-active') | NO   |     | active            |                |
| added_on   | datetime                   | NO   |     | CURRENT_TIMESTAMP |                |
| updated_on | datetime                   | YES  |     | NULL              |                |
+------------+----------------------------+------+-----+-------------------+----------------+

表格:匹配

+------------+---------------------------------------+------+-----+-------------------+----------------+
| Field      | Type                                  | Null | Key | Default           | Extra          |
+------------+---------------------------------------+------+-----+-------------------+----------------+
| id         | int(11)                               | NO   | PRI | NULL              | auto_increment |
| team_one   | int(11)                               | NO   | MUL | NULL              |                |
| team_two   | int(11)                               | NO   |     | NULL              |                |
| added_on   | datetime                              | NO   |     | CURRENT_TIMESTAMP |                |
| match_type | enum('pool','quarter','semi','final') | NO   |     | pool              |                |
| sets       | smallint(2)                           | NO   |     | 1                 |                |
+------------+---------------------------------------+------+-----+-------------------+----------------+

表格:匹配结果

+-----------+----------+------+-----+-------------------+----------------+
| Field     | Type     | Null | Key | Default           | Extra          |
+-----------+----------+------+-----+-------------------+----------------+
| id        | int(11)  | NO   | PRI | NULL              | auto_increment |
| match_id  | int(11)  | NO   | MUL | NULL              |                |
| winner_id | int(11)  | NO   | MUL | NULL              |                |
| added_on  | datetime | NO   |     | CURRENT_TIMESTAMP |                |
+-----------+----------+------+-----+-------------------+----------------+

【问题讨论】:

在应用程序代码中使用计数器可能是最好的解决方案。但是如果时间不多,可以搜索“mysql+rank”。 我不确定,但你可以通过CASE查看计数。 【参考方案1】:

这里有一个类似的问题:

How to add ROW INDEX as a column to SQL SELECT query?

从你想要的问题扩展:

SET @row_num = 0;
SELECT
    T.id, T.name, T.status, IFNULL(T.image, 'no-image.png') AS DP,
    (SELECT COUNT(*)
    FROM badminton_matches MT
    WHERE (MT.team_one = T.id OR MT.team_two = T.id)) 
      AS played,
    (SELECT COUNT(*)
    FROM badminton_match_results R
    WHERE R.winner_id = T.id) AS won,
    (SELECT COUNT(*)
    FROM badminton_matches MT JOIN badminton_match_results MR
        ON (MR.match_id = MT.id)
    WHERE (MT.team_one = T.id OR MT.team_two = T.id) AND MR.winner_id != T.id) AS lost,
    (
       ((SELECT COUNT(*)
    FROM badminton_match_results R
    WHERE R.winner_id = T.id) * 2) 
         + 
       ((SELECT COUNT(*)
    FROM badminton_match_results R JOIN badminton_matches M ON (M.id = R.match_id AND M.match_type = 'quarter')
    WHERE R.winner_id = T.id))
      ) AS Points,

    /* here is the magic */
    (@row_num
:= @row_num + 1) < 4 AS row_index

    FROM badminton_teams T
    ORDER BY
(Points) DESC

这将添加一个名为 row_index 的额外列,其中 1 表示在前 3 中,0 表示不在前 3 中。

请记住,您必须在每个 SELECT 之前并在同一会话中调用 SET

【讨论】:

谢谢,@David Newcomb 这是一个旧线程,我已经解决了,但让我们选择它作为答案,因为我使用了你提到的相同方法。

以上是关于MySQL 查找排名前 3 的团队的主要内容,如果未能解决你的问题,请参考以下文章

MySQL排名前n的排名和其他同组的总和

《团队-获取豆瓣电影排名250-项目进度》

3 月数据库排名:PostgreSQL 再涨

MySQL - 排名前 5 的畅销计划或课程

sql 从两列PHP MySql中查找排名

用sql语句,查询每个班级成绩排名前三名的学生姓名