2016-07-28 21 views
0

meine aktuelle Abfrage sieht in etwa so aus. Ich habe versucht, es zu optimieren, aber ich hatte bisher kein Glück. Mein Ziel ist es, für jeden Spieler den Unterschied in stat_value zwischen dem aktuellen Tag und dem vorherigen Tag zu erhalten und ihn dann zu bestellen. Der aktuelle Code funktioniert gut, fühlt sich aber für mich nicht optimiert an. Die? Werte werden mit Java gefüllt.MySQL Abfrage über mehrere Zeilen hinweg optimieren

SELECT t1.stat_value - 
     (SELECT stat_value 
      FROM leaderheadsplayersdata_daily t2 
     WHERE t2.player_id = t1.player_id 
      AND t2.day = ? 
      AND t2.stat_type = ? 
     LIMIT 1 
     ) as sum 
    , (SELECT name 
      FROM leaderheadsplayers 
     WHERE leaderheadsplayers.player_id = t1.player_id 
     LIMIT 1 
     ) 
    FROM leaderheadsplayersdata_daily t1 
    WHERE day = ? 
    AND stat_type = ? 
    ORDER 
     BY sum DESC LIMIT 100 

Tabellenstruktur:

Dies ist die Haupttabelle, die die Spieler-ID und Benutzername enthält.

CREATE TABLE IF NOT EXISTS `leaderheadsplayers` 
(player_id INTEGER PRIMARY KEY AUTO_INCREMENT 
,uuid VARCHAR(36) NOT NULL UNIQUE 
,name VARCHAR(16) NOT NULL 
,last_join DATETIME 
) ENGINE = InnoDB 

Dies ist die Tabelle mit den täglichen Daten.

CREATE TABLE IF NOT EXISTS leaderheadsplayersdata_daily 
(player_id INTEGER NOT NULL 
,stat_value DOUBLE NOT NULL 
,stat_type VARCHAR(16) NOT NULL 
,day INTEGER NOT NULL 
,FOREIGN KEY (player_id) REFERENCES leaderheadsplayers(player_id) ON DELETE CASCADE 
,PRIMARY KEY(player_id, stat_type, day) 
) ENGINE = InnoDB 

Vielen Dank im Voraus

+0

Beschreibung Ihrer Tabellenstruktur würde helfen, eine Antwort vorzuschlagen – evilpenguin

+0

Datenbankstruktur hinzugefügt. –

+0

Können Sie die Ausgabe von EXPLAIN für Ihre Abfrage bereitstellen? – ultrajohn

Antwort

1

Weil Sie nur 2 Tage haben, können Sie auf der leaderheadsplayersdata_daily Tabelle ein Doppel beitreten tun.

Es würde wie folgt aussehen:

SELECT 
    p.player_id, 
    p.name, 
    (dc.stat_value-dp.statvalue) AS difference, 
    dc.day, 
FROM leaderheadsplayers p 
JOIN leaderheadsplayersdata_daily dc ON p.player_id = dc.player_id 
JOIN leaderheadsplayersdata_daily dp ON p.player_id = dp.player_id and dp.day = (dc.day-1) 
WHERE dc.day = ?CURRENT_DAY? 
ORDER BY difference DESC 

dc steht für "Datum aktuelle". dp steht für "Datum vorher". p steht für "Spieler".

Fügen Sie für eine gute Leistung Indizes für die Spalten player_id (in beiden Tabellen) und day hinzu.

Sorry, ich habe nicht getestet, habe nicht ideea, wenn ich Syntaxfehler oder Zeug habe. Auch bitte ?CURRENT_DAY? mit dem aktuellen Tag ersetzen und andere Bedingungen in WHERE Klausel hinzufügen, je nach Bedarf

Wenn ORDER BY difference DESC nicht funktioniert, tut nur ORDER BY (dc.stat_value-dp.statvalue) DESC.

Sie haben viele Unterabfragen, Sie sehen aus, als könnten Sie einen Blick auf einige documentation about JOINs werfen. Sie sind wirklich nützlich.

+0

Vielen Dank. Die Abfrage ist momentan unglaublich schnell. –

+0

Wir freuen uns, Ihnen behilflich zu sein. :) – evilpenguin

-1

Alternativ können Sie Folgendes versuchen. Lassen Sie mich wissen, wie diese Version, die implizite Triple Join-Tarif mit dem oben vorgeschlagenen verwendet, die explizite Triple Join verwendet. Vielen Dank.

SELECT t3.player_id, improvement FROM 
    (SELECT t1.player_id as player_id, (t1.stat_value - t2.stat_value) as improvement 
     FROM leaderheadsplayersdata_daily t1 INNER JOIN leaderheadsplayersdata_daily t2 
     on t1.player_id = t2.player_id and t1.stat_type = t2.stat_type 
      and t2.day = ? and t1.day = ?) as t3 
    INNER JOIN leaderheadsplayers on 
     t3.player_id = leaderheadsplayers.player_id 
      ORDER BY improvement DESC LIMIT 100; 
Verwandte Themen