Mysql为每个用户选择每组的前N个分数

时间:2015-04-23 00:46:38

标签: mysql sql

我试图用一个简单的"帮助一个好友。他的高尔夫球队的网站。我试图使用的数据库将存储每轮完成的所有玩家分数。还有两种类型的游戏将被播放和存储。示例如下:

ID        Game Type     Score  
1             a           12
1             a           12
1             a           1
1             a           15
1             a           15
1             b           12
1             b           5
1             b           10
1             b           12
1             b           5
1             b           10
2             a           6
2             a           9
2             a           1
2             a           3 
2             a           2
2             b           8
2             b           10
2             b           15
2             b           3 
2             b           12

我要做的是,为每个用户选择游戏类型A的前3个分数,并为每个用户从游戏类型B中选择前2个分数。 我需要选择产生什么,以便我可以总结每个球员的得分:

ID        Game Type     Score  
1             a           12
1             a           15
1             a           15
1             b           12
1             b           12

2             a           6
2             a           9
2             a           3 
2             b           15
2             b           12

我在Select highest 3 scores in each day for every user找到了来自bonCodigo的类似问题和解决方案。我把他的sql改成了这个:

-- for top 2 sum by user by each day
SELECT userid, sum(score), type
FROM scores t1
where 3 >=
(SELECT count(*) 
 from scores t2
 where t1.score <= t2.score
 and t1.userid = t2.userid
 and t1.type = t2.type
 order by t2.score desc)
group by userid, type 
;

-- for all two days top 2 sum by user
SELECT userid, sum(score)
FROM scores t1
where 3 >=
(SELECT count(*) 
 from scores t2
 where t1.score <= t2.score
 and t1.userid = t2.userid
 and t1.type = t2.type
 order by t2.score desc)
group by userid
;

我遇到的问题是,如果我想要前3名,但第3和第4分相等,那么它将不会获得第3高分;只有前两名。附件是我试图使用的sqlfiddle。任何有关如何使用前三名的帮助,无论它们是否全部相等!谢谢!

my sqlfiddle

1 个答案:

答案 0 :(得分:0)

所以,由于无法放弃这一点,我已经想出了这个怪物,使用存储过程来获得你想要的输出(基本上复制你在应用程序级别做的事情来实现同样的结果)。

create procedure leaderboard()
begin
  declare uid int;
  declare done int default 0;
    declare cur1 cursor for select distinct userid from score;
  declare continue handler for not found set done = 1;
  drop table if exists score_temp;
  create temporary table score_temp(userid int, score int, type int);
  open cur1;
  read_loop: LOOP
    fetch cur1 into uid;
    if done then
      close cur1;
      leave read_loop;
    end if;
    INNERBLOCK: begin
      declare done2 int default 0;       
      declare i_userid int;
      declare i_type int;
      declare i_score int;
      declare cur2 cursor for select * from score where userid = uid and type = 1 order by score desc limit 3;
      declare continue handler for not found set done2 = 1;
      open cur2;
      inner_loop: LOOP
        fetch cur2 into i_userid, i_score, i_type;
        if done2 then
          close cur2;
          leave inner_loop;
        end if;
        insert into score_temp values (i_userid, i_score, i_type);
      end loop inner_loop;
    end INNERBLOCK;
    INNERBLOCK: begin
      declare done2 int default 0;       
      declare i_userid int;
      declare i_type int;
      declare i_score int;
      declare cur2 cursor for select * from score where userid = uid and type = 2 order by score desc limit 2;
      declare continue handler for not found set done2 = 1;
      open cur2;
      inner_loop: LOOP
        fetch cur2 into i_userid, i_score, i_type;
        if done2 then
          close cur2;
          leave inner_loop;
        end if;
        insert into score_temp values (i_userid, i_score, i_type);
      end loop inner_loop;
    end INNERBLOCK;
  end loop read_loop;
  select * from score_temp;
end

然后获取您的排行榜,您的查询是 call leaderboard();

演示小提琴:http://sqlfiddle.com/#!2/569fb2/1