Question

Mon schéma

Je les tableaux ci-dessous

table             notes/example values
------------------------------------------------
users (
  id
  email           # "foo@example.com"
)                 

games (           
  id              
  name            # "Space Invaders", "Asteroids", "Centipede"
)                 

players (         
  id              
  name            # "uber dude"
  user_id         # player belongs to user
  game_id         # player belongs to game
)                 

scores (          
  id              
  player_id       # belongs to one player
  value           # 50
  created_at      # "2010-09-10",   "2010-08-05"
  month           # "2010-09",      "2010-08"
)

Je dois créer deux rapports.

1) Les meilleurs joueurs

Les meilleurs joueurs performants (somme toutes les partitions pour chaque joueur) pour le plus récent 4 mois. Montrer les 10 pour chaque mois.

    2010-07         2010-08           2010-09    2010-10
 1  plyA 5,000 pts  plyB  9,400 pts   ...        ...
    Centipede       Solitaire

 2  plyB 3,600 pts  plyC  8,200 pts   ...        ...
    Asteroids       Centipede       

 3  plyC 2,900 pts  plyA  7,000 pts   ...        ...
    Centipede       Centipede

 4  ...             ...               ...        ...
 5  ...             ...               ...        ...
 6  ...             ...               ...        ...
 7  ...             ...               ...        ...
 8  ...             ...               ...        ...
 9  ...             ...               ...        ...
10  ...             ...               ...        ...

2) Top Utilisateurs:

Les meilleurs utilisateurs performants (somme toutes les partitions pour chaque joueur pour chaque utilisateur) pour la Le plus récent 4 mois. Montrer les 10 pour chaque mois.

    2010-07           2010-08             2010-09    2010-10
 1  userA 50,000 pts  userB 51,400 pts    ...        ...
 2  userB 40,500 pts  userA 39,300 pts    ...        ...
 3  userC 40,200 pts  userC 37,000 pts    ...        ...
 4  ...               ...                 ...        ...
 5  ...               ...                 ...        ...
 6  ...               ...                 ...        ...
 7  ...               ...                 ...        ...
 8  ...               ...                 ...        ...
 9  ...               ...                 ...        ...
10  ...               ...                 ...        ...

MySQL Voir aide

Pour se joindre à des fins, j'ai vue stockée pour aider les requête mois pour les rapports. Il reviendra toujours les plus récentes 4 mois.

report_months (
  month
)

SELECT * FROM report_months;

2010-07
2010-08
2010-09
2010-10

Le problème

Dans le rapport n ° 1, par exemple, je peux obtenir les sommes assez facilement.

select
  p.name        as player_name,
  g.name        as game_name,
  s.month       as month,
  sum(s.score)  as sum_score

from players  as p

join games    as g
  on g.id = p.game_id

join scores   as s
  on s.player_id = p.id

join report_months as rm  -- handy view helper
  on rm.month = s.month

group by
  p.name, g.name

order by
  sum(s.score) desc

-- I can't do this :(
-- limit 0, 40

Cependant, je ne peux pas simplement aller chercher le top 40 et les résultats répartis sur 4 mois, car cela ne me garantir 10 pour chaque mois.

La question

Comment puis-je modifier ma requête pour faire en sorte que je reçois 10 pour chaque mois?

Était-ce utile?

La solution

Je ne tenterait pas de faire une requête SQL qui par mois comme sous forme de tableaux que vous avez indiqué.

Au lieu de cela, la requête les 10 joueurs par mois sous forme de lignes, non comme colonnes:

Month    Rank  Player  TotalScore  Game
2010-07     1    plyA   5,000 pts  Centipede
2010-07     2    plyB   3,600 pts  Asteroids
2010-07     3    plyC   2,900 pts  Centipede
...
2010-08     1    plyB   9,400 pts  Solitaire
2010-08     2    plyC   8,200 pts  Centipede
2010-08     3    plyA   7,000 pts  Centipede
...

Cela devient un problème de greatest-n-per-group, où n est 10.

CREATE VIEW PlayerScoresByMonth AS
  SELECT month, player_id, SUM(value) AS score
  FROM scores
  GROUP BY month, player_id;

SELECT s1.month, COUNT(s2.month)+1 AS Rank, s1.player_id, s1.score AS TotalScore
FROM PlayerScoresByMonth s1
LEFT OUTER JOIN PlayerScoresByMonth s2 ON s1.month = s2.month 
  AND (s1.score < s2.score OR s1.score = s2.score AND s1.player_id < s2.player_id)
GROUP BY s1.month, s1.player_id
HAVING COUNT(*) < 10
ORDER BY s1.month, Rank;

(qui est non testé, mais devrait vous aider à démarrer)

Ensuite, vous devez écrire un code d'application pour récupérer les résultats de cette requête et séparer les listes par mois, et présenter les données mais vous allez le faire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top