如何编写足球排名系统算法

时间:2015-05-19 04:48:47

标签: mysql algorithm

我现在正在开发足球网站并尝试编写排名表的编码。我觉得必须有算法来制定排名表如下。

enter image description here

表结构是,

tb_result
-   matchno
-   team1
-   team2
-   score1
-   score2

我会像

一样输入数据
Matchno team1       team2       score1      score2
1       A-Team      B-Team          1       3
1       C-Team      D-Team          3       0
2       D-Team      A-Team          3       3
2       B-Team      C-Team          2       5   

所以我想知道可以开发任何算法或公式来获得排名表。

1 个答案:

答案 0 :(得分:5)

没有'简单'使用您给出的表结构进行查询以执行您想要的操作。

那说它很有可能。您需要一个查询来获取每个团队的总目标:

select team, sum(score1) score_for
         from
           (select team1 as team, score1
              from matches
            union all
            select team2, score2
              from matches
           ) qq
         group by team

然后,您需要再次使用相同的查询来获取目标:

select team1 as team, sum(score2) score_against
         from
           (select team1, score2
              from matches
            union all
            select team2, score1
              from matches
           ) qq
        group by team

我们得到的结果与我们在第一个查询中检索到的结果相反。

还可以将这两个查询合并为一个查询:

select team, sum(score_for), sum(score_against)
from
(
  select team1 as team, score1 as score_for, score2 as score_against
    from matches
  union all
  select team2 as team, score2 as score_for, score1 as score_against
    from matches
)q
group by team;

我们还需要一个查询来计算胜利,亏损和平局:

select team1 as team, count(case when result = 1 then result end) w, count(case when result = 0 then result end) d, count(case when result = -1 then result end) l
       from
         (select team1, case when score1 > score2 then 1 when score1 = score2 then 0 else -1 end result
            from matches
          union all
          select team2, case when score2 > score1 then 1 when score2 = score1 then 0 else -1 end result
            from matches
         ) qq
       group by team1

我们在那里使用条件聚合为win,loss和draw分配值(分别为1,-1和0)

最后,我们需要计算每支球队的比赛次数。

select team, count(*) gp
       from 
        (select team1 as team
           from matches
         union all
         select team2 as team
           from matches
        ) qq
       group by team

也可以从前面的任何一个查询中获取此值,我只是将其分开,就像显示思考过程的目标/目标一样。在制作中,你肯定希望将它们结合起来以提高性能。

在这里的所有情况下,我们必须执行union,因为团队可以出现在team1或team2中,我们需要将其同质化。对于不同的表模式,这是不必要的,但这完全是另一回事。

最后,我们需要做的就是将所有这些加在一起并添加一个排名,我们可以非常简单地做到这一点,因为它们很方便地都有一个team列。为方便起见,我假设你有一张teams表,如果你没有,那就太傻了。

反正:

select  @rank := @rank + 1 as '#', q.*
from (
select teams.team, gp, score_for gf, score_against ga, score_for - score_against gd, w, l, d, (w * 3) + d as pts
  from  teams
    inner join
      (select team, sum(score1) score_for
         from
           (select team1 as team, score1
              from matches
            union all
            select team2, score2
              from matches
           ) qq
         group by team
       ) q1
       on teams.team = q1.team
    inner join
      (select team1 as team, sum(score2) score_against
         from
           (select team1, score2
              from matches
            union all
            select team2, score1
              from matches
           ) qq
        group by team
     ) q2
     on teams.team = q2.team
   inner join
     (select team1 as team, count(case when result = 1 then result end) w, count(case when result = 0 then result end) d, count(case when result = -1 then result end) l
       from
         (select team1, case when score1 > score2 then 1 when score1 = score2 then 0 else -1 end result
            from matches
          union all
          select team2, case when score2 > score1 then 1 when score2 = score1 then 0 else -1 end result
            from matches
         ) qq
       group by team1
     ) q3
     on teams.team = q3.team
   inner join
     (select team, count(*) gp
       from 
        (select team1 as team
           from matches
         union all
         select team2 as team
           from matches
        ) qq
       group by team
     ) q4
     on teams.team = q4.team
   order by pts desc
) q, (select @rank := 0) z

此查询还会为您计算points。我的假设是

  • win = 3分
  • 损失= 0分
  • draw = 1 point

demo here