Door
G Jansma
op 01-12-2015 18:58
gewijzigd op 01-12-2015 19:00
6.616 views
Hallo,
Ik heb een vraag over Mysql. Ik wil op basis van uitslagen een stand opmaken, maar ik kom er niet uit. De puntentelling is enigszins gecompliceerd, en ik weet niet of ik deze het beste in een table kan stoppen of in de query zelf.
Even een korte uiteg. De stand wordt gebaseerd op de punten behaald in het afgelopen jaar, een beetje zoals in het tennis ook gebeurd. Er zijn twee categoriën A en B, en vier niveau's wedstrijden (N1,N2,N3,N4). Daarnaast is er nog een extra moeilijkheid, namelijk dat van de wedstrijden van niveau N3 en N4 alleen de beste 5 resultaten uit het afgelopen jaar tellen.
De code zou er - voor zover mijn kennis reikt - dus ongeveer zo moeten uitzien denk ik:
SELECT * FROM speler AS s
JOIN uitslagen AS u ON s.id = u.uitslag_naam
JOIN kalender AS k ON k.categorie = u.uitslag_categorie AND k.seizoen = u.uitslag_seizoen AND k.kalender_id = u.uitslag_id
....
GROUP BY uitslag_id
AND datum BETWEEN '".$datum."' - INTERVAL 1 YEAR AND '".$datum."'
ORDER BY datum DESC
'Datum' komt uit kalender, en $datum haal ik op uit de URL met de GET-functie. Omdat elke wedstrijd maar één keer meetelt moet Group BY uitslag_id ervoor zorgen dat er van elke wedstrijd maar één resultaat is, en door middel van de Order by datum de recentste editie. Al moet de stand uiteindelijk worden 'georderd' op basis van degene met de meeste punten. Ik heb al veel gezocht ivm het rekenwerk, maar ik weet niet hoe dat moet, dus dat heb ik maar even open gelaten.
N1 - 1 van 1
N2 - 3 van 3
N3 - 5 van X (alleen vijf beste resultaten tellen mee)
N4 - 5 van X (alleen vijf beste resultaten tellen mee)
Even uit de vrije hand dus zoiets:
IF uitslag_categorie = A AND uitslag_niveau = N1 AND uitslag_positie = 1 --> 20
Ik heb ook een table 'puntentelling' gemaakt bestaande uit de kolommen categorie - niveau - p1 - p2 - p3 etc. maar ik weet niet of dat de manier is waarop dat zou moeten.
Nav je eerste vraag: van wat heb je maar 1 nodig?
Ik dacht juist dat je van wedstrijden van het laatste jaar de punten wilde optellen (en bij N3 en N4 alleen de beste).
Nav je tweede vraag:
ik denk dat je in 2 stukken moet hakken vanwege de N3 en N4: zoals ik om 8:24 ongeveer aangaf.
Eerst een paar union selects om de juiste wedstrijden op te halen (teruglezend zie ik wel dat je niet de laatste 5, maar de beste 5 wilt. Je zult dus de ORDER BY datum DESC moeten vervangen door ORDER BY punten DESC).
Als je die werken hebt, kun je dat in een subquery stoppen om op te tellen.
Recap: de 1e query zie 8:24, de 2e query wordt dan:
SELECT uitslag_naam, SUM(punten) FROM (.. en hier komt de 1e query)
GROUP BY uitslag_naam
ORDER BY SUM(punten) DESC
Ik denk dat we elkaar (bijna) begrijpen. Het gaat over de uitslagen in het afgelopen jaar. Voor N1 en N2 tellen alle wedstrijden mee uit het afgelopen jaar, en voor N3 en N4 alleen de beste 5 resultaten uit het afgelopen jaar.
Maar het kan daarnaast dus voorkomen dat een wedstrijd door datumwisseling etc. twee keer in 365 dagen plaatsvindt. Ik wil dus eigenlijk alleen de laatste editie opnemen in de stand.
Bedoel je dit met 8.24?
SELECT uitslag_naam, SUM(punten) FROM (
SELECT * FROM uitslagen
WHERE uitslag_niveau in ("N1", "N2") -- alles van N1 en N2
UNION
SELECT * FROM (SELECT * FROM uitslagen
WHERE uitslag_niveau = "N3"
AND datum BETWEEN '".$datum."' - INTERVAL 1 YEAR AND '".$datum."
ORDER BY punten DESC LIMIT 5) AS u2
UNION
SELECT * FROM (SELECT * FROM uitslagen
WHERE uitslag_niveau = "N4"
AND datum BETWEEN '".$datum."' - INTERVAL 1 YEAR AND '".$datum."
ORDER BY punten DESC LIMIT 5) AS u3
)
GROUP BY uitslag_naam
ORDER BY SUM(punten) DESC
Ik zou dan denk ik, als ik je goed begrijp, een extra rij toevoegen met bijvoorbeeld de naam 'competitie' of 'status' of wat dan ook. Dan daar bijvoorbeeld 1 in laten vullen voor het oude jaar en 2 voor het nieuwe. Dan kijk je met een query naar de status en zoek je alle bijbehorende statussen bij elkaar en uit status 2 dan wat je daarvan nodig hebt... of zoiets... een scheidingsmanier.
Zal vast ook wel te doen zijn met een code of query die op een bepaalde manier naar de datums kijkt. Maar ik noem dit maar als mogelijkheid.
In Kalender staat één rij met de wedstrijd, per categorie, niveau en seizoen.
1 - 2015-12-03 - A - N1 - 2014-2015
1 - 2014-12-02 - A - N1 - 2013-2014
(kalender_id, datum, categorie, niveau, seizoen_
Uitslagen is vrijwel hetzelfde per rij, maar daar is elke rij dus een resultaat van een speler.
1 - A - N1 - 2014-2015 - Jan - 1
1 - A - N1 - 2014-2015 - Piet - 2
1 - A - N1 - 2014-2015 - Klaas - 3
1 - A - N1 - 2013-2014 - Joop - 1
1 - A - N1 - 2013-2014 - Piet - 2
1 - A - N1 - 2013-2014 - Jan - 3
(uitslag_id, uitslag_categorie, uitslag_niveau, uitslag_seizoen, uitslag_naam (eigenlijk id ervan), uitslag_positie)
OK dat is de data (ik neem aan dat kalender_id en uitslag_id niet allemaal 1 zijn).
En leg nu je verzoek van de laatste wedstrijd nog eens uit aan de hand van de data.
Overigens is het niet zo'n goed idee om data te herhalen. Als er velden uit uitslagen afhankelijk zijn van de kalender (zoals categorie, niveau en seizoen) is het beter om ze daar weg te laten en te vervangen door de kalender id. Normaliseren heet dat.
De id 1 is inderdaad wedstrijd 1, wedstrijd 2 is 2 etc.
Door middel van de joins haal ik de datum op uit kalender, en vindt hij zeg maar de resultaten die bij die editie horen.
Maar stel dus dat de wedstrijd binnen 365 dagen (obv de datum) twee keer plaatsvindt, dan telt dus het resultaat van beide wedstrijden mee. Maar dat wil ik niet. Dan zou Jan dus 1e en 3e zijn, en 36 punten krijgen. Ik wil dat dan alleen de laatste editie van wedsrijd 1 meetelt, en dan heeft Jan dus 20 punten.
Ik denk niet dat dat het makkelijker maakt. Omdat de stand gaat over de laatste 365 dagen tellen dus wedstrijden uit het seizoen 2014-2015 en 2015-2016 mee. Ik wil dus dat elk uitslag_id maar 1x meegaat in het optellen van de punten. Ik dacht meer aan iets met Distinct, Group by of Limit ...
Ik vrees dat ik niet begrijp wat je wilt bereiken.
Ik raak telkens in de war. Aan de ene kant wil je alleen de laatste wedstrijd, aan de andere kant de 5 beste resultaten. Van wie of wat? Van een speler, van de kalender?