Optimierung in MySQL.

...komplette Frage anzeigen

2 Antworten

so hier gehts weiter :)

SELECT ( @n := @n + 1 ) AS 'Rang',
       sub.n            AS 'Name',
       sub.c            AS 'Anzahl Spielabende',
       sub.s            AS 'Schnitt',
       sub.p            AS 'Punkte gesamt',
       sub.g            AS 'Spiele gewonnen',
       sub.v            AS 'Spiele verloren',
       sub.b            AS 'Beste Serie',
       sub.k            AS 'Kleinste Serie'
    FROM   (
                    SELECT cs.`nachname`           n,
                    Round(Avg(ergebnis), 2) s,
                    Sum(ergebnis)           p,
                    Sum(gewonnen)           g,
                    Sum(verloren)           v,
                    Max(ergebnis)           b,
                    Min(ergebnis)           k,
                    cs.`ismember`           i,
                    Count(*)                c,
                    CASE
                        WHEN Count(*) > ( 0.56 * recc ) 
                        THEN 1
                        ELSE 0
                    end                     
                    AS                      q
                        FROM   `custom_ergebnisse` ce
                            INNER JOIN `custom_skatplayers`cs
                                ON ce.`fk_skatplayers_id` = cs.`player_id`
                            INNER JOIN `custom_spielabend` csa
                                ON csa.id = ce.`fk_spielabend_id`
                            INNER JOIN (
                                            SELECT max(`lfd_nr`)     recc 
                                                FROM `custom_spielabend` 
                                                WHERE year(datum) = year(now())
                                )        rec
                        WHERE  Year(csa.datum) = Year(Now())
                        GROUP  BY cs.`nachname`
            ) AS sub
    INNER JOIN (SELECT @n := 0) x
    ORDER  BY sub.q DESC,
              sub.i DESC,
              sub.s DESC;  

Und ja leider muss ich das mit sonem riesen Subselect im FROM-Teil machen, weil sonst mein Counter nicht richtig arbeitet :)

Für mein Ergebnis der letzten Serie hab ich ein Workaround gemacht, indem ich eine Prozedur geschrieben habe.

DELIMITER //
CREATE PROCEDURE getlast()
BEGIN
    SELECT cs.`nachname`           n,
               Round(Avg(ergebnis), 2) s,
               count(*)                c                
        FROM   `custom_ergebnisse` ce
        INNER JOIN `custom_skatplayers`cs
                       ON ce.`fk_skatplayers_id` = cs.`player_id`
               INNER JOIN `custom_spielabend` csa 
                    ON csa.ID = ce.`fk_spielabend_id`
        WHERE csa.`lfd_nr` <= (SELECT max(`custom_spielabend`.`lfd_nr`)-1 AND year(`custom_spielabend`.datum) = year(now()) FROM `custom_spielabend`)


        GROUP  BY cs.`nachname`;

END;
//
DELIMITER ;

Ich hätte dann für die Schnittänderung was Ähnliches erstellt.

Aber das ist alles so umständlich. Vielleicht denke ich mal wieder zu kompliziert. Habt ihr zufällig ne Idee, wie ich alles unter einen Hut kriege, in einem schönen Query? :)

Wer gute Ideen oder Tipps hat, immer her damit.

Für gute Antworten winkt eine hilfreichste Antwort.

MfG

Alex

Alextoexplain 13.08.2014, 23:30

Falls einer wissen will, was das mit dem CASE auf sich hat..., man muss mindestens an 56% der Serien teilgenommen haben, sonst fällt man aus der Wertung raus ;)

0

Warum so kompliziert? Berechne die Ergebnisse mit einem PHP Skript und schreibe dann die Ergebnisse zyklisch in eine Ergebniss-Tabelle. (per CronJob)

Die Ergebniss-Tabelle kannst du dann mit einem einfachen SELECT ausgeben.

Alextoexplain 13.08.2014, 23:34

Genau das will ich vermeiden. Ich bin der Meinung dass die Datenbank das schneller und besser kann, als ein PHP Skript das dann nämlich definitiv umfangreicher wird. Da ich das Ganze auf ner Webseite (Wordpress) ausgeben will, bin ich mir nicht sicher, ob es Sinn macht, das dann nur regelmäßig zu designen. Ich hätte halt gesagt, alle meine Seiten werden immer beim Aufrufen frisch generiert. Wobei es für statische Listen sogar noch Sinn machen würde, aber spätestens für persönliche Statistiken, das hab ich auch geplant, wirds da blöd =)

0
Gwarn 13.08.2014, 23:43
@Alextoexplain

Ich würde es halt so lösen. Die Ausgabe wird dann wesentlich schneller, da nur noch ein SELECT erforderlich ist. Klar _kann_ man alle Logik in die DB auslagern. Ob es Sinn macht steht auf einem anderen Blatt. :)

Die persönlichen Statistiken sind doch auch immer nur wieder die gleichen Berechnungen wie die für die Gesamt-Statistik, nur eben mit einem Parameter mehr für den User.

Mir stellt sich zudem die Frage, wie oft überhaupt neue Daten in die DB kommen und somit eine Neuberechnung erforderlich wird.

Sprich: Muß der Query wirklich bei jedem Seitenaufruf rechnen oder reicht es aus, die Neuberechnung 1x anzustoßen, nachdem neue Daten vorhanden sind? ;)

1
Alextoexplain 13.08.2014, 23:47
@Gwarn

Ja gut, wie du sagst, es kommen nur einmal die Woche neue Spieldaten rein, im Regelfall. Ich könnte aber auch nen View erstellen und den dann speichern.

Weil SQL find ich immer schöner als auf PHP auszulagern. Nur hab ich bei den Views dann wieder das Problem, dass es da so viele Einschränkungen gibt, dass ich befürchten muss, dass ich meinen Query nicht mal in nen View packen kann.

0
maximilianus7 15.08.2014, 12:04
@Alextoexplain

Halt: eine view ist nur eine abkürzende Schreibweise. Ein SELECT * FROM viewname stösst die ganze Abfrage an, wie sie in CREATE VIEW formuliert ist. Die Daten sind ja in den eigentlichen Tabellen verteilt, bzw. werden berechnet. Die View-Daten werden nicht eingefroren. Wenn du das willst, müsstest du eine neue Tabelle mit den aufbereiteten Daten erstellen.

Gruß, MAx.

1
Alextoexplain 15.08.2014, 13:54
@maximilianus7

Sicher? Ah okay. Ich hatte das so in Erinnerung, dass Views eine Momentaufnahme darstellen. Würde ja vom Begriff auch Sinn machen. Ich hab die noch nie gebraucht und nur mal kurz angeschaut. Aber du wirst schon Recht haben ;)

0

Was möchtest Du wissen?