Ligasystem (JOIN und LIMIT)

Akihisa

Well-known member
ID: 332118
L
21 Oktober 2008
165
13
Hi,

erstmal sorry wegen dem doofen Titel, ich weiß aber nicht wie ich's so kruz beschreiben soll.
Folgende Situation Ich versuche grad eine Art Ligasystem zu basteln, dazu hab ich zwei Tabellen angelegt. Eine in der die ID, Namen und das Jahr gespeichert sind und eine indem der Monat, in dem der Spieler teilgenommen hat, und die Punkte, die er dabei erreicht hat, gespeichert werden

Tabelle: Name
ID|Name|Year
1|Hans Maier|2009
2|Peter Schmidt|2009

Tabelle: Punkte
Name_ID|Month|Points
1|1|15
1|3|18
1|8|10
2|1|12
2|2|25
2|3|16
2|6|15
2|11|19

Nun möchte ich, zwecks Übersicht, nicht alle Spieler auf einmal ausgeben, sonder nur die ersten 25, und die restlichen mittels Blätterfunktion. LIMIT kann ich dafür aber nicht einsetzen, da ja nicht jeder Spieler gleich oft an den Turnieren teilgenommen hat.
Mein Ansatz war jetzt erst einmal, dass ich die Ausgabe anhand der ID's beschränke:
PHP:
$seite  = 1;
$eintraege_pro_seite = 25;
$start =  $seite * $eintraege_pro_seite - $eintraege_pro_seite;
$ende = $start + $eintraege_pro_seite + 1;

$sql='SELECT
	Name.ID,
	Name.Name,
	Name.Year,
	Punkte.Month,
	Punkte.Points
FROM
	Name
JOIN
	Punkte
ON
	Name.ID = Punkte.Name_ID
WHERE
	Name.ID > '.$start.' AND Name.ID < '.$ende.'
ORDER BY
Name.Year DESC,
Punkte.Name_ID ASC';

// abfrage abschicken usw.

Problem hierbei ist jetzt, aber wenn sich erstens unter den ersten 25 ID's nur Teilnehmer aus dem Jahr 2009 befinden und unter den nächsten 25 welche aus dem Jahr 2010, dann werden logischerweise auf Seite 1 Teilnehmer aus dem Jahre 2009 und auf der zweiten Seite Teilnehmer aus 2009 und 2010 dargestellt.
Problem Nummer 2 ist eine Suchfunktion, die nach den Namen sucht. Die WHERE-Klausel wird mit
PHP:
name.Name LIKE "%'.$search.'%"
erweitert (die Suchanfrage wird selbstverständlich vor SQL-Injections geschützt). Problem hierbei: Es werden nur die ersten 25 ID's durchsucht.

Solltet ihr noch irgendwelche Infos brauchen, einfach sagen und ich ergänz es.
Ich hoffe ihr könnt mir irgendwie helfen.

Danke schonmal
 
Ein Möglichkeit wäre alle Punkte mit GROUP BY zusammen zu zählen und die Zeilen dann mit LIMIT zu beschränken. Sollte Irgendwer dann genauere Daten (also die Monate mit den Punkten) wissen wollen, muss er auf einen Link klicken und kommt auf eine genauere Auflistung.

Aber vielleicht kennt wer eine bessere Lösung.
 
LIMIT kann ich dafür aber nicht einsetzen, da ja nicht jeder Spieler gleich oft an den Turnieren teilgenommen hat.
Du kannst schon, allerdings musst du das vorher machen, also nur auf die Name-Relation:
Code:
[FONT=Courier New][B][COLOR=#9932cc]SELECT[/COLOR][/B] name.*, punkte.*
[B][COLOR=#9932cc]FROM[/COLOR][/B] punkte
[B][COLOR=#9932cc]JOIN[/COLOR][/B] name ...
[B][COLOR=#9932cc]WHERE[/COLOR][/B] name.id [B][COLOR=#9932cc]IN[/COLOR][/B] (
  [B][COLOR=#9932cc]SELECT[/COLOR][/B] id[B]
  [/B][B][COLOR=#9932cc]FROM[/COLOR][/B] name
  [B][COLOR=#9932cc]LIMIT[/COLOR][/B] 50
);[/FONT]
 
Du kannst schon, allerdings musst du das vorher machen, also nur auf die Name-Relation:
Code:
[FONT=Courier New][B][COLOR=#9932cc]SELECT[/COLOR][/B] name.*, punkte.*
[B][COLOR=#9932cc]FROM[/COLOR][/B] punkte
[B][COLOR=#9932cc]JOIN[/COLOR][/B] name ...
[B][COLOR=#9932cc]WHERE[/COLOR][/B] name.id [B][COLOR=#9932cc]IN[/COLOR][/B] (
  [B][COLOR=#9932cc]SELECT[/COLOR][/B] id[B]
  [/B][B][COLOR=#9932cc]FROM[/COLOR][/B] name
  [B][COLOR=#9932cc]LIMIT[/COLOR][/B] 50
);[/FONT]

SubSelect würde auch gehen :D Bin kein Freund dessen/Habe es noch nie eingesetzt
 
Du kannst schon, allerdings musst du das vorher machen, also nur auf die Name-Relation:
Code:
[FONT=Courier New][B][COLOR=#9932cc]SELECT[/COLOR][/B] name.*, punkte.*
[B][COLOR=#9932cc]FROM[/COLOR][/B] punkte
[B][COLOR=#9932cc]JOIN[/COLOR][/B] name ...
[B][COLOR=#9932cc]WHERE[/COLOR][/B] name.id [B][COLOR=#9932cc]IN[/COLOR][/B] (
  [B][COLOR=#9932cc]SELECT[/COLOR][/B] id[B]
  [/B][B][COLOR=#9932cc]FROM[/COLOR][/B] name
  [B][COLOR=#9932cc]LIMIT[/COLOR][/B] 50
);[/FONT]

Klingt gut, doch leider will MySQL da nicht mitmachen. :(

Fehlertext: This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Fehlernummer: 1235
MySQL-Version: 5.0.45
 
Dann eben Handarbeit. Innere Query in PHP ausführen und Ergebnisse im Array sammeln, imploden und zweite Query ausführen.
 
Code:
SET @count = 0;
SELECT name.*, punkte.*
FROM punkte
JOIN name ...
WHERE name.id IN (
  SELECT id
  FROM name
  WHERE (@count:=@count+1) < 50
);

macht zwar einen fulltable-Scan für die name-Tabelle, funktioniert aber :biggrin:
 
Hab's jetzt per array und implode gemacht. Funktioniert alles.
Danke für die schnelle Hilfe :)
 
Beachte, dass ein implode() von einem leerem Array zum leeren String und später dann zur SQL-Fehlermeldung "... IN () ..." führt, wenn du das nicht abfängst.