Klassement 'beste twintig' veranderen
Voor het klassement van mijn mahjongclubje heb ik een algemeen klassement bedacht waarbij de beste 20 resultaten van iedere speler tellen.
In het bestand functions.php is dat als volgt gedefinieerd:
function standmetscoresmetid($id) {
// Get database connection
$db = JFactory::getDbo();
$qry = "SELECT SpelerID, SpelerNaam, Average, Aantal, Hoogste, Laagste "
. "FROM vwStand "
. "WHERE SeizoenID = " . $db->quote($id). " AND AANTAL<>0 ORDER BY Average DESC;";
$db->setQuery($qry);
$db->query();
$result=$db->loadRowList();
$tbl = new HTML_Table(null, 'display', 1, 0, 4, array('width'=>'100%'));
}
Maar deze methode bevalt me niet meer zo goed. Ik zou ook de "slechtste" resultaten willen laten
meetellen. Bijvoorbeeld de beste 10 en de slechtste 10, en daar dan het gemiddelde van.
Maar ik heb geen idee hoe ik de 'slechtste 10' moet definiëren.
Iemand een hint?? Alvast bedankt!
Maar ik neem aan dat je de resultaten (of zelfs het aantal resultaten) niet bijhoudt in de rij bij de gebruiker... maar die gewoon elke keer opnieuw berekent/bekijkt in de tabel met resultaten...
Eddy E op 16/08/2015 17:18:48:
Maar ik neem aan dat je de resultaten (of zelfs het aantal resultaten) niet bijhoudt in de rij bij de gebruiker... maar die gewoon elke keer opnieuw berekent/bekijkt in de tabel met resultaten...
Ja, dat klopt. (Het nadeel is ook dat het openen van de html-pagina waarop het klassement staat, langt duurt
omdat alle resultaten opnieuw geëvalueerd moeten worden.)
Gewijzigd op 16/08/2015 18:42:17 door Martin Rep
Uhm je database indeling aub? (dus welke tabellen heb je en welke kolommen zitten er in de tabellen)
Je kunt de html-tabel hier 'live' zien, help dat?
http://www.furiten.nl/klassement1516.html
(deze tabel heeft het bovengemelde probleem nog nauwelijks; op
dit moment is er slechts één speler die 20+ wedstrijden heeft
gespeeld)
Gewijzigd op 16/08/2015 21:59:12 door Martin Rep
bedankt!
Hoezo? Op dit forum zijn er mensen genoeg die jouw kunnen helpen..
Daar had ik op gehoopt, Maarten, maar tot nu toe kom ik er niet uit. Maar de hint is duidelijk: ik geef het nog niet op! Misschien meer geduld nodig… ;-)
Code (php)
1
2
3
4
5
2
3
4
5
SELECT SpelerID, SpelerNaam, Average, Aantal, Hoogste, Laagste
FROM vwStand
WHERE SeizoenID = 5
ORDER BY average_score DESC
LIMIT 20
FROM vwStand
WHERE SeizoenID = 5
ORDER BY average_score DESC
LIMIT 20
te doen.
die bijvoorbeeld al 100 partijen heeft gespeeld (van wie in het door mij bedoelde model dus 60 partijen niet worden meegenomen in het gemiddelde).
Dank!
Kun je iets met deze denkrichting mischien?
Code (php)
1
2
3
4
2
3
4
SELECT ((high.hoogste + low.laagste) / 20) as average FROM
(SELECT SUM(Average) as hoogste FROM vwStand order by Average DESC limit 10) as high,
(SELECT SUM(Average) as laagste FROM vwStand order by Average ASC limit 10) as low
;
(SELECT SUM(Average) as hoogste FROM vwStand order by Average DESC limit 10) as high,
(SELECT SUM(Average) as laagste FROM vwStand order by Average ASC limit 10) as low
;
Dit zou volgens mij het gemiddelde van de hoogste en laagste 10 gemiddelden moeten geven, maar bind me er niet op vast.
Denk dat dit meer de richting is waar je in moet denken als je het allemaal in SQL wil doen.
Ik ga ermee aan de slag en meld me weer als ik meer weet.
Dank (^^)
De hoogste 10 en de laagste 10 overlappen dan.
Gewijzigd op 18/08/2015 12:42:16 door Jan de Laet
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
SELECT
s.SpelerID,
s.SpelerNaam,
s.Aantal,
AVG(CASE
WHEN r.rijnummer <= 10 THEN r.score
ELSE
CASE
WHEN r.rijnummer > 10 AND r.rijnummer > s.Aantal - 10 THEN r.score
ELSE NULL END
END) gemiddelde,
MAX(CASE
WHEN r.rijnummer <= 10 THEN r.score
ELSE
CASE
WHEN r.rijnummer > 10 AND r.rijnummer > s.Aantal - 10 THEN r.score
ELSE NULL END
END) hoogste,
MIN(CASE
WHEN r.rijnummer <= 10 THEN r.score
ELSE
CASE
WHEN r.rijnummer > 10 AND r.rijnummer > s.Aantal - 10 THEN r.score
ELSE NULL END
END) laagste
FROM
(
SELECT
d.SpelerID,
d.SpelerNaam,
COUNT(*) Aantal
FROM
deelnemers d
JOIN
resultaten r1
ON d.SpelerID = r1.SpelerID
WHERE r1.SeizoenID = 5
GROUP BY d.SpelerID
) s
JOIN
(
SELECT
@rijnummer := CASE WHEN ro.SpelerID <> @id THEN 1 ELSE @rijnummer + 1 END rijnummer,
@id := ro.SpelerID SpelerID,
ro.score
FROM
(
SELECT
d1.SpelerID,
r2.Score
FROM
deelnemers d1
JOIN
resultaten r2
ON d1.SpelerID = r2.SpelerID
WHERE r2.SeizoenID = 5
ORDER BY d1.SpelerID, r2.score
) ro
CROSS JOIN
(
SELECT
@rijnummer := 1,
@id := 0
) var
) r
ON s.SpelerID = r.SpelerID
GROUP BY s.SpelerID, s.SpelerNaam, s.Aantal
ORDER BY gemiddelde DESC,s.Aantal
s.SpelerID,
s.SpelerNaam,
s.Aantal,
AVG(CASE
WHEN r.rijnummer <= 10 THEN r.score
ELSE
CASE
WHEN r.rijnummer > 10 AND r.rijnummer > s.Aantal - 10 THEN r.score
ELSE NULL END
END) gemiddelde,
MAX(CASE
WHEN r.rijnummer <= 10 THEN r.score
ELSE
CASE
WHEN r.rijnummer > 10 AND r.rijnummer > s.Aantal - 10 THEN r.score
ELSE NULL END
END) hoogste,
MIN(CASE
WHEN r.rijnummer <= 10 THEN r.score
ELSE
CASE
WHEN r.rijnummer > 10 AND r.rijnummer > s.Aantal - 10 THEN r.score
ELSE NULL END
END) laagste
FROM
(
SELECT
d.SpelerID,
d.SpelerNaam,
COUNT(*) Aantal
FROM
deelnemers d
JOIN
resultaten r1
ON d.SpelerID = r1.SpelerID
WHERE r1.SeizoenID = 5
GROUP BY d.SpelerID
) s
JOIN
(
SELECT
@rijnummer := CASE WHEN ro.SpelerID <> @id THEN 1 ELSE @rijnummer + 1 END rijnummer,
@id := ro.SpelerID SpelerID,
ro.score
FROM
(
SELECT
d1.SpelerID,
r2.Score
FROM
deelnemers d1
JOIN
resultaten r2
ON d1.SpelerID = r2.SpelerID
WHERE r2.SeizoenID = 5
ORDER BY d1.SpelerID, r2.score
) ro
CROSS JOIN
(
SELECT
@rijnummer := 1,
@id := 0
) var
) r
ON s.SpelerID = r.SpelerID
GROUP BY s.SpelerID, s.SpelerNaam, s.Aantal
ORDER BY gemiddelde DESC,s.Aantal
De eerste subquery haalt de spelers en het totaal aantal gespeelde partijen op.
De tweede haalt alle resultaten op en nummert deze per speler (in PostGres/Oracle/SQLserver etc gaat dit veel eenvoudiger).
Dit wordt dan gebruikt om te bepalen welke resultaten mee moeten worden genomen in de aggegrate functies (NULL wordt genegeerd)
Edit:
JOIN Conditions toegevoegd
Gewijzigd op 19/08/2015 13:14:11 door Ger van Steenderen
Ger van Steenderen op 19/08/2015 11:45:00:
De eerste subquery haalt de spelers en het totaal aantal gespeelde partijen op.
De tweede haalt alle resultaten op en nummert deze per speler (in PostGres/Oracle/SQLserver etc gaat dit veel eenvoudiger).
Dit wordt dan gebruikt om te bepalen welke resultaten mee moeten worden genomen in de aggegrate functies (NULL wordt genegeerd)
De eerste subquery haalt de spelers en het totaal aantal gespeelde partijen op.
De tweede haalt alle resultaten op en nummert deze per speler (in PostGres/Oracle/SQLserver etc gaat dit veel eenvoudiger).
Dit wordt dan gebruikt om te bepalen welke resultaten mee moeten worden genomen in de aggegrate functies (NULL wordt genegeerd)
Ger, dit ziet er heel indrukwekkend uit, maar toch kom ik er niet helemaal uit. Kun jij me de weg wijzen in wat voor bestand ik deze code moet plakken?
Dank!
Gewijzigd op 29/08/2015 20:55:31 door Martin Rep
Probeer de query eens gewoon uit en kijk met print_r() wat hij terug geeft.
Eén vraag nog. Er zijn grote verschillen in de aantallen wedstrijden die spelers afwerken. Nu loop je de (theoretische) kans dat een speler één keer speelt, een topscore haalt en het dan verder voor gezien houdt. Op die manier zou hij kampioen worden.
In onze huidige ranking lossen we dat op door alle spelers die minder dan 20 wedstrijden hebben gespeeld, 30.000 punten voor iedere niet-gespeelde wedstrijd te geven.Dat zou ook in de nieuwe oplossing passen.
Hoe kunnen we dat implementeren in jouw script?
Nogmaals enorm bedankt, ben hier erg blij mee.
Martin
Toevoeging op 29/10/2015 06:56:35:
Martin Rep op 28/10/2015 23:06:41:
Kan ik je een PM sturen, en zo ja, hoe?
…Je hebt 'm al! (^^)