如何从2个不同的表中计算用户排名

时间:2017-10-25 08:07:11

标签: mysql

我有一个users表,其中包含phase1和phase2列,我需要计算每个阶段的用户排名并将其存储在这些字段中。

排名是根据不同的表points计算的,其中我有每个用户的逐点数。

我想做的是

  1. 按阶段对每个用户的所有积分求和,并根据
  2. 计算他的等级
  3. 如果用户点数相等,则比较等级1的总和,如果相等则比较等级2的总和
  4. 在每个阶段更新users表及其排名
  5. 这是我的新表与一些演示数据的外观 sql fiddle demo

    目前我使用以下代码来计算我的旧表中的排名,其中排名和用户信息都在同一个表中

    old sql fiddle demo

    update users a
    join (
      select id,
      (
          select count(distinct total) 
          from users d
          where c.total < d.total
      ) +1 rank
      from users c
    ) b on a.id = b.id
    set a.rank = b.rank
    

1 个答案:

答案 0 :(得分:1)

oracle中有分析函数,名为rank()和dense_rank(),可用于获取结果。

当你使用mysql时,我试图将这些函数转换为mysql等价物。 您可以使用以下查询获得所需的结果,您可以使用该查询来更新用户表。如果对于成绩也有分数的逻辑,你可能需要进一步改变它。

set @pk1 ='';
set @rn1 =1;
set @tot ='';
set @val =1;


SELECT  id,
        name,
        phase,
        phasetotal,
        denseRank
FROM
(
  SELECT  id,
          name,
          phase,
          phasetotal,
          @rn1 := if(@pk1=phase, @rn1+@val,1) as denseRank,
          @val := if(@pk1=phase, if(@tot=phasetotal, @val+1, 1),1) as value,
          @pk1 := phase,
          @tot := phasetotal     
  FROM
  (
        select users.id,users.name, points.phase, sum(points.points) 
        as phasetotal from users,points where users.id = points.userid 
        group by users.id, points.phase order by points.phase, phasetotal desc, points.grade1 desc, points.grade2 desc    
) A
) B;

这是更新查询

set @pk1 ='';
set @rn1 =1;
set @tot ='';
set @val =1;


UPDATE users u join (
SELECT  id,
        name,
        phase,
        phasetotal,
        denseRank
FROM
(
  SELECT  id,
          name,
          phase,
          phasetotal,
          @rn1 := if(@pk1=phase, @rn1+@val,1) as denseRank,
          @val := if(@pk1=phase, if(@tot=phasetotal, @val+1, 1),1) as value,
          @pk1 := phase,
          @tot := phasetotal     
  FROM
  (
        select users.id,users.name, points.phase, sum(points.points) 
        as phasetotal from users,points where users.id = points.userid 
        group by users.id, points.phase order by points.phase, phasetotal desc, points.grade1 desc, points.grade2 desc    
) A
) B ) C on u.id = C.id
   SET u.phase1 = CASE WHEN C.phase = 1 and u.phase1 = 0 THEN C.denseRank ELSE u.phase1 END,
       u.phase2 = CASE WHEN C.phase = 2 and u.phase2 = 0 THEN C.denseRank ELSE u.phase2 END;