Frage

My Schema

Ich habe die folgenden Tabellen

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"
)

Ich brauche zwei Berichte zu erstellen.

1) Top-Spieler

beste Performance Spieler (Summe alle Noten für jeden Spieler) für die letzten 4 Monate. Zeige die Top 10 für jeden Monat.

    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 Benutzer:

beste Performance Benutzer (alle Noten für jeden Benutzer für jeden Spieler SUM) für die letzte 4 Monate. Zeige die Top 10 für jeden Monat.

    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 View Helfer

Für die Zwecke verbinden, ich habe eine gespeicherte Ansicht zu Hilfe Abfrage der Monate für die Berichte. Es wird immer die letzten 4 Monate zurück.

report_months (
  month
)

SELECT * FROM report_months;

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

Das Problem

Im Bericht # 1, zum Beispiel, kann ich die Summen ziemlich leicht.

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

Allerdings kann ich nicht einfach die Top-40-Ergebnisse holen und sie sich über 4 Monate verteilt, da dies würde mir nicht garantieren, 10 für jeden Monat.

Die Frage

Wie kann ich meine Abfrage ändern, um sicherzustellen, dass ich 10 für jeden Monat bekommen würde?

War es hilfreich?

Lösung

Ich würde nicht versuchen, eine SQL-Abfrage zu machen, dass eine tabellarische Monat, wie Sie gezeigt haben.

Stattdessen Abfrage der Top 10 Spieler pro Monat als Zeilen, nicht als Spalt:

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
...

Dies wird zu einem greatest-n-per-group Problem, wo n ist 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;

(die nicht getestet ist, aber sollte Ihnen den Start)

Dann müssen Sie einige Anwendungscode schreiben, um die Ergebnisse dieser Abfrage zu holen und die Listen von Monat zu trennen, und die Daten weisen jedoch Sie, dass tun würden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top