在 mySQL 和 VIEW 创建中分配排名

Posted

技术标签:

【中文标题】在 mySQL 和 VIEW 创建中分配排名【英文标题】:Assiging rank in mySQL and VIEW creation 【发布时间】:2013-04-29 13:37:30 【问题描述】:

我有一张名为积分榜的表格,其中包含每支球队的积分、净胜球和进球数。这是表结构和数据。

CREATE TABLE standings (
  team_id int(3) unsigned NOT NULL AUTO_INCREMENT,
  points int(2) unsigned DEFAULT 0,
  goal_difference int(2) unsigned DEFAULT 0,
  goals_for int(2) unsigned DEFAULT 0,
  PRIMARY KEY (team_id)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1;

insert into standings(team_id,points,goal_difference,goals_for) values (1,20,2,17);
insert into standings(team_id,points,goal_difference,goals_for) values (2,14,8,15);
insert into standings(team_id,points,goal_difference,goals_for) values (3,9,2,11);
insert into standings(team_id,points,goal_difference,goals_for) values (4,14,10,12);
insert into standings(team_id,points,goal_difference,goals_for) values (5,17,10,19);
insert into standings(team_id,points,goal_difference,goals_for) values (6,5,-11,7);
insert into standings(team_id,points,goal_difference,goals_for) values (7,14,10,10);
insert into standings(team_id,points,goal_difference,goals_for) values (8,9,2,14);
insert into standings(team_id,points,goal_difference,goals_for) values (9,12,1,10);
insert into standings(team_id,points,goal_difference,goals_for) values (10,9,2,14);
commit;

我想按积分、goal_difference 和goals_for 的降序对该表进行排序,并根据此顺序为每个团队分配排名。由于 mysql 没有 RANK 功能,所以在搜索了这个站点后我来了 完成这个查询。

SELECT CASE
          WHEN @prev_value = concat(points,'-',goal_difference,'-',goals_for)
          THEN
             @cur_rank
          WHEN @prev_value := concat(points,'-',goal_difference,'-',goals_for)
          THEN
             @cur_rank := @cur_rank + 1
       END
          AS rank, s.team_id, s.points, s.goal_difference, s.goals_for
  FROM standings s, (SELECT @cur_rank := 0) p, (SELECT @prev_rank := 0) q, (SELECT     @prev_value := NULL) r
 ORDER BY s.points DESC, s.goal_difference DESC, s.goals_for DESC;

到目前为止一切顺利。现在我有两个问题。

    如果您看到上述查询的结果,则第 8 队和第 10 队之间并列第 7 名。因此,我想将排名第 9 的团队分配给下一个排名第 3 的团队。我该如何做到这一点,而无需在查询中添加更多列。

    我想使用此查询创建一个 VIEW。但是 mySQL 不允许我创建一个并给出错误,'View's SELECT contains a variable or parameter'。请建议如何为此创建 VIEW。

    CREATE VIEW view_standings
    AS
       SELECT CASE
         WHEN @prev_value = concat(points,'-',goal_difference,'-',goals_for)
         THEN
            @cur_rank
         WHEN @prev_value := concat(points,'-',goal_difference,'-',goals_for)
         THEN
            @cur_rank := @cur_rank + 1
      END
         AS rank,s.team_id,s.points,s.goal_difference,s.goals_for
    FROM standings s,(SELECT @cur_rank := 0) p,(SELECT @prev_rank := 0) q,(SELECT @prev_value := NULL) r
    ORDER BY s.points DESC, s.goal_difference DESC, s.goals_for DESC;
    

【问题讨论】:

【参考方案1】:

您还可以使用相关子查询进行排名。如果您的数据量适中,这可能会产生大量计算。

 select s.*,
        (select 1+COUNT(*)
         from standings s2
         where s2.points > s.points or
               (s2.points = s.points and s2.goal_difference > s.goal_difference) or
               (s2.points = s.points and s2.goal_difference = s.goal_difference and s2.goals_for > sys.goals_for
        ) as ranking
 from standings s

因为它在from 子句中只有一个子查询,所以您可以将其用作视图。

我认为您可以通过索引号为standings(points, goal_difference, goals_for) 来提高性能。

【讨论】:

谢谢戈登。这正是我想要的。

以上是关于在 mySQL 和 VIEW 创建中分配排名的主要内容,如果未能解决你的问题,请参考以下文章

MySQL数据库中的高级(进阶)语句:VIEW视图联集和常见计算

Angular创建模块并分配路由

ORACLE 数据库权限分配,我想分配给某个用户创建视图并只能能查看修改自己创建的视图的权限 这个怎么弄

在MySQL中实现Rank高级排名函数

MySQL 分配在更新查询中仅匹配一次

使用 SELECT * 创建 MYSQL VIEW