Es gibt so ein tolles Zitat:
“Was nicht auf einer einzigen Manuskriptseite zusammengefasst werden kann, ist nicht durchdacht und nicht entscheidungsreif.”
Wenn man das auf meine SQL-Abfrage überträgt, muss ich wohl eingestehen, dass diese Abfrage undurchdacht wäre. Ist sie aber nicht! Ich habe 3 Tage an dieser Abfrage zugebracht, damit sie das Ergebnis ausgibt, welches sie jetzt ausgibt.
Die Abfrage ist für ein Wettkampf, der aus mehreren Einzeldisziplinen besteht, die an unterschiedlichen Tagen veranstaltet werden (zeitgleich und hintereinander). Der Wettkampf ist für Teams. Für jede Einzeldisziplin ist die DisziplinId, TeamId, Platz, Datum, Punktestand vorhanden. Allerdings wird für die Gesamtwertung nicht der Punktestand in der Einzeldisziplin genommen, sondern inder Gesamtwertung werden neue Punkte anhand der Platzierung in der Einzeldisziplin vergeben – z.B. so: Platz 1 – 100 Punkte, Platz 2 – 90 Punkte, usw.
Es klingt schon so natürlich sprachlich kompliziert und ehe ich hier weitere Einzelheiten versuche zu erklären, platziere ich hier einfach die 117 Zeilen lange SQL-Abfrage:
SELECT @anzTeam := (SELECT COUNT(*) FROM pentathlon_team WHERE freigeschaltet='1'), @seq := @anzTeam + 1, @rank := @anzTeam, @letzteDatum := (SELECT DISTINCT SUBSTR(MIN(zeitpunkt),1,10) FROM pentathlon_score WHERE pentathlon_credits != 0), @letztePunkte := 999999; SELECT gesamt.teamid, @seq := IF(@letzteDatum = gesamt.zeitpunkt, @seq - 1, @anzTeam) AS seq, /*Sequenz ...,3,2,1 je Datum*/ @rank := IF(@letztePunkte = gesamt.punkte, @rank, @seq) AS rank, /*Der Rank eines Teams (wenn gleiche Punktzahl gleicher Rank)*/ @letztePunkte := gesamt.punkte AS punkte, @letzteDatum := gesamt.zeitpunkt AS zeitpunkt FROM (SELECT einzelgesamt.teamid, SUM(einzelgesamt.punkte) AS punkte, einzelgesamt.zeitpunkt AS zeitpunkt FROM (SELECT DISTINCT normale_daten.zeitpunkt, normale_daten.teamid, normale_daten.disziplinid, IF(normale_daten.punkte IS NOT NULL, normale_daten.punkte, IF((SELECT von FROM pentathlon_disziplin WHERE disziplinid = normale_daten.disziplinid) > normale_daten.zeitpunkt, 0, /*Disziplin noch nicht gestartet*/ (SELECT DISTINCT /*Disziplin ist beendet: Punkte des letzten Stands*/ IF (pentathlon_score.rank > 25, 0, /*Keine Punkte mehr ab Platz 25*/ pentathlon_punkte.punkte ) AS punkte FROM pentathlon_score LEFT JOIN pentathlon_punkte ON pentathlon_score.rank = pentathlon_punkte.rank WHERE pentathlon_score.disziplinid = normale_daten.disziplinid AND pentathlon_score.teamid = normale_daten.teamid AND pentathlon_score.zeitpunkt = (SELECT DISTINCT MAX(zeitpunkt) FROM pentathlon_score WHERE disziplinid = normale_daten.disziplinid) ) ) ) AS punkte, IF(normale_daten.rank IS NOT NULL, normale_daten.rank, IF((SELECT von FROM pentathlon_disziplin WHERE disziplinid = normale_daten.disziplinid) > normale_daten.zeitpunkt, 0, /*Disziplin noch nicht gestartet*/ (SELECT DISTINCT /*Disziplin ist beendet: Punkte des letzten Stands*/ pentathlon_score.rank FROM pentathlon_score WHERE pentathlon_score.disziplinid = normale_daten.disziplinid AND pentathlon_score.teamid = normale_daten.teamid AND pentathlon_score.zeitpunkt = (SELECT DISTINCT MAX(zeitpunkt) FROM pentathlon_score WHERE disziplinid = normale_daten.disziplinid) ) ) ) AS rank FROM (SELECT DISTINCT alle_daten.zeitpunkt, alle_daten.teamid, alle_daten.disziplinid, pentathlon_score.rank, IF (pentathlon_score.rank > 25, 0, /*Keine Punkte mehr ab Platz 25*/ pentathlon_punkte.punkte ) AS punkte FROM (SELECT DISTINCT SUBSTR(pentathlon_score.zeitpunkt,1,10) as zeitpunkt, pentathlon_team.teamid, pentathlon_disziplin.disziplinid, pentathlon_teamdisziplin.webrpc FROM pentathlon_score JOIN pentathlon_team JOIN pentathlon_disziplin INNER JOIN pentathlon_teamdisziplin ON pentathlon_disziplin.disziplinid = pentathlon_teamdisziplin.disziplinid WHERE pentathlon_score.pentathlon_credits != 0 AND pentathlon_team.freigeschaltet = '1') AS alle_daten LEFT JOIN pentathlon_score ON alle_daten.teamid = pentathlon_score.teamid AND alle_daten.disziplinid = pentathlon_score.disziplinid AND IF(SUBSTR(alle_daten.webrpc,1,33) = 'http://www.worldcommunitygrid.org', alle_daten.zeitpunkt = SUBSTR(pentathlon_score.zeitpunkt,1,10), alle_daten.zeitpunkt = DATE_ADD(SUBSTR(pentathlon_score.zeitpunkt,1,10), INTERVAL -1 DAY) AND SUBSTR(pentathlon_score.zeitpunkt,12,2)='01' ) LEFT JOIN pentathlon_punkte ON pentathlon_score.rank = pentathlon_punkte.rank) AS normale_daten ) AS einzelgesamt GROUP BY einzelgesamt.zeitpunkt, einzelgesamt.teamid ) AS gesamt ORDER BY gesamt.zeitpunkt, gesamt.punkte DESC
Natürlich hätte ich das auch alles durch einfache Abfragen lösen können, die ich dann in PHP zusammenfüge, aber in PHP ist das einfügen und sortieren der Daten so ineffizient.
Die @variable sind User-Variablen in MySQL, mit denen man die Platzierung in der Abfrage berechnen kann.
Jetzt würde ich meine Fähigkeiten in SQL mit einer 1,2 benoten.. ;)
Auch interessant:
















