2014-02-24 17 views
5

Im Verbindungs ​​3 Tabellen eine Tabelle mit den Nutzern präsentieren punkten höchstePHP MySQL Highscore-Tabelle

Meine Tabellen

game_log:

---ID---user_ID---score---time--- 
| 1  52  567  10 | 
| 2  53  641  13 | 
| 3  52  465  8 | 
| 4  53  451  14 | 
--------------------------------- 

Benutzer:

---ID---name---countyid--- 
| 52 Dave  1  | 
| 53 John  2  | 
    ------------------------ 

Kreis :

---countyid---countyname--- 
    |  1 Orange wichit | 
    |  2 Orange clemts | 
    -------------------------- 

SQL:

SELECT * FROM game_log 
INNER JOIN users ON game_log.user_ID=users.ID 
INNER JOIN county ON users.countyid=county.countyid 
ORDER BY game_log.score DESC , game_log.time LIMIT 20"; 

Above Code mir dieses Ergebnis liefert:

Rank---Name--------County------Score---Time 
1  John  Orange clemts 641  13 
2  Dave  Orange wichit 567  10 
3  John  Orange clemts 465  8 
4  Dave  Orange wichit 451  14 

Mein Problem ist, dass ich die Highscore-Tabelle, die den Top-20-Benutzer mit der höchsten Punktzahl, nicht angezeigt werden soll die 20 höchsten Punktzahlen.

So:

Rank---Name--------County------Score---Time 
1  John  Orange clemts 641  13 
2  Dave  Orange wichit 567  10 

Need som Hilfe bei diesem, nicht vertraut sind mit Verbindungs ​​Tabellen ;-)

+0

Nehmen Sie an einer Unterabfrage teil, die die maximale Punktzahl für jede Gruppe auswählt. – Mihai

+0

Welchen Datensatz möchten Sie für einen Benutzer zurückgeben, wenn sie 2 Instanzen mit der gleichen Punktzahl haben, und diese Punktzahl ist die höchste für sie, und sie sind in den Top 20? Der mit dem niedrigsten oder höchsten Zeitwert? Oder etwas anderes? –

Antwort

2

Bei diesem Ansatz werden die 20 besten Nutzer und die höchste Punktzahl jedes Nutzers angezeigt. Wenn sie mehrere Instanzen mit derselben Punktzahl haben, werden die Informationen für die früheste angezeigt (niedrigster Zeitwert für diesen Nutzer und Punktzahl).

SELECT * 
    FROM game_log gl 
INNER JOIN users u 
    ON gl.user_ID = u.ID 
INNER JOIN county c 
    ON u.countyid = c.countyid 
WHERE not exists (select 1 
      from game_log gl2 
     where gl2.user_id = gl.user_id 
      and gl2.score > gl.score) 
    and not exists (select 1 
      from game_log gl2 
     where gl2.user_id = gl.user_id 
      and gl2.time < gl.time 
      and gl2.score = gl.score) 
ORDER BY gl.score DESC, gl.time LIMIT 20; 

Ohne dies zu tun, wenn der gleiche Benutzer in den Top 20 die gleiche Punktzahl 2+ mal hatte, würden sie aufgeführt werden 2+ mal, und Sie würden nicht wieder 20 Leute von LIMIT 20, weil die Verwendung derselben Person würde Aufnahme N Zeilen aus diesem 20.

SQL Fiddle hier Daten mit einer Krawatte zeigt: http://sqlfiddle.com/#!2/0ac931/5/0

+0

Perfekt, das hat mir geholfen! Genau das, was ich brauchte! –

1

Ich würde dies tun mit dem not exists Ansatz die höchste Punktzahl für jeden Benutzer zu erhalten. Der Rest der Abfrage ist das gleiche:

SELECT * 
FROM game_log gl INNER JOIN 
    users u 
    ON gl.user_ID = u.ID INNER JOIN 
    county c 
    ON u.countyid = c.countyid 
WHERE not exists (select 1 
        from game_log gl2 
        where gl2.user_id = gl.user_id and gl2.score > gl.score 
       ) 
ORDER BY gl.score DESC, gl.time 
LIMIT 20; 

Die where Klausel sagt „diese Zeile halten, wenn keine andere Zeile für den gleichen Benutzer eine höhere Punktzahl hat“.

Ein anderer Weg, dies mit dem Aggregationsansatz zu tun ist:

SELECT * 
FROM (select user_id, max(score) as maxscore 
     from game_log gl 
     group by user_id 
    ) gl INNER JOIN 
    users u 
    ON gl.user_ID = u.ID INNER JOIN 
    county c 
    ON u.countyid = c.countyid 
ORDER BY gl.maxscore DESC 
LIMIT 20; 

Aber diese Methode verliert die Informationen über time. Es ist möglich, das einzuschließen, aber es macht die Abfrage komplizierter.

2

GROUP BY sollte die Arbeit machen.

SELECT users.ID, users.name, county.countyname, MAX(game_log.score) AS score, game_log.time 
FROM game_log 
INNER JOIN users ON game_log.user_ID = users.ID 
INNER JOIN county ON users.countyid = county.countyid 
GROUP BY game_log.user_ID 
ORDER BY game_log.score DESC, game_log.time 
LIMIT 20; 

Probieren Sie es mit SQL Fiddle aus.