2015-04-23 4 views
0

Я пытаюсь помочь приятелю с «простым» веб-сайтом для его группы гольфа. База данных, которую я пытаюсь использовать, сохранит все баллы игроков за каждый завершенный раунд. Есть также два типа игр, которые будут воспроизводиться и храниться. Пример ниже:Mysql select top N баллов за группу ДЛЯ КАЖДОГО пользователя

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 

То, что я пытаюсь сделать это, выберите верхнюю 3 оценку типа игры для каждого пользователя и выбрать верхние 2 оценок от типа игр B для каждого пользователя. Что мне нужно ВЫБРАТЬ, чтобы получить таким образом я могу затем суммировать баллы для каждого игрока:

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 

я нашел подобный вопрос и решение от bonCodigo на Select highest 3 scores in each day for every user. Я изменил свой 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, который я пытался использовать. Любая помощь в том, как заставить его использовать верхнюю 3, независимо от того, все они равны или нет! Благодаря!

my sqlfiddle

+0

MySQL это дерьмо для этого вы могли бы быть лучше всего делать это в приложении. –

+0

Спасибо. Это будет иметь в виду. Я нашел очень близкое решение, но это просто немного. Я отредактировал свой вопрос, чтобы подумать. Я не могу комментировать другой ответ bc, я просто noob! Надеюсь, кто-то сможет ответить на это! –

+0

хорошо .. там вы идете. в основном это сложно, потому что mysql не поддерживает 'limit' в коррелированном подзапросе, иначе было бы относительно просто –

ответ

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

+0

Ничего себе, спасибо Пале за вашу помощь и взломать. Я просто проснулся, но посмотрю на него немного позже. Ура! –

+0

как я сказал в комментариях к вопросу - это недостаток mysql. Если есть способ сделать это без процедуры, я этого не знаю. Логический способ не работает, потому что у mysql нет этой функции. –

Смежные вопросы