Mam problem z zapytaniem, to jest moje stare pytanie, które zostało wcześniej rozwiązane mysql uzyskaj pozycję rankingową zgrupowaną z połączoną tabelą

Problem polega na tym, że gdy dwóch graczy ma ten sam wynik, zapytanie zwraca tę samą pozycję w rankingu, np. 1-1-2-3 ecc. Jak mogę to naprawić? Na stole gracza znajduje się również player_tickets (to jest liczba rozegranych gier) i player_date to jest znacznik czasu.

Pomyślałem, że najpierw powinienem oprzeć swój ranking na player_score, potem player_tickets i na końcu player_date

To jest moje starsze zapytanie

SELECT *, 
       (SELECT 1 + Count(*) 
        FROM   players p2 
        WHERE  p2.`player_game` = p.`player_game` 
               AND p2.player_score > p.player_score  
               AND p2.player_status = 0) AS ranking 
FROM   players p 
ORDER  BY `player_game`, 
          player_score DESC
2
geggiamarti 31 marzec 2020, 17:02

3 odpowiedzi

Najlepsza odpowiedź

Po prostu dodaj kryteria rankingu do klauzuli WHERE:

SELECT *, 
  (
    SELECT 1 + COUNT(*)
    FROM   players p2 
    WHERE  p2.player_game = p.player_game 
    AND
    (
      (p2.player_score > p.player_score) OR
      (p2.player_score = p.player_score AND p2.player_tickets > p.player_tickets) OR
      (p2.player_score = p.player_score AND p2.player_tickets = p.player_tickets AND p2.player_date > p.player_date) OR
      (p2.player_score = p.player_score AND p2.player_tickets = p.player_tickets AND p2.player_date = p.player_date AND p2.player_id > p.player_id)
    )
  ) AS ranking 
FROM players p 
ORDER BY player_game, player_score DESC;
1
Thorsten Kettner 31 marzec 2020, 14:55

Możesz dodać dodatkowe porównania w podzapytaniu. Lub łatwiej, użyj zmiennych:

select p.*,
       @rn := if(@g = player_game, @rn + 1,
                 if(@g := player_game, 1, 1)
                ) as ranking
from (select p.*
      from players p
      order by player_game, player_score desc, player_tickets desc, player_date desc
     ) p cross join
     (select @rn := 0, @g := 0) as seqnum;

W nowszych wersjach używałbyś po prostu row_number(), jeśli nie chcesz krawatów.

0
Gordon Linoff 31 marzec 2020, 14:44

Możesz po prostu dodać więcej kolumn do order by funkcji okna:

rank() over (
    partition by player_game_id 
    order by player_score desc, player_tickets desc, player_date
) as rank

Jeśli naprawdę chcesz uniknąć podwójnego zajmowania tej samej rangi, możesz również użyć row_number(), co gwarantuje to - w przypadku remisów row_number() wpływa na różne liczby (których kolejność jest zatem niezdefiniowana).

1
GMB 31 marzec 2020, 14:07