PDO & MySQL: Unterabfrage mit dynamischer Zeit? Weg zur Lösung mit Join durch Vermeiden von while-Schleife?

eim Versuch, einige Bestandsdaten abzurufen, nachdem ein bestimmter Satz von Kriterien aus einer Datenbank ausgelöst wurde, erhalte ich eine langsame Antwort, die hauptsächlich auf der Verwendung dynamischer Daten basiert. Ich habe mich gezwungen, in eine while-Schleife zu gehen, um Berechnungen durchzuführen. Ich habe mich gefragt, ob es eine Möglichkeit gibt, dies möglichst in einer Abfrage zusammenzufassen. Das Folgende ist ein vereinfachtes Beispiel für den von mir verwendeten Code und möglicherweise eine mögliche Lösung.

Das Hauptproblem ist, dass die Abfrage sehr langsam ist und nur mit einer Geschwindigkeit von etwa 29 Zeilen pro Sekunde ausgeführt wird. (Die Abfrage von 11000 Zeilen dauert ungefähr 6 Minuten.)

$sql_while_0 = "
SELECT 
    k.*, 
    y.exchange
FROM stocks k
JOIN symbols y
    ON k.id = y.id
WHERE   
    (
    y.exchange = 'NASDAQ CM' OR
    y.exchange = 'NASDAQ GM'
    )
    AND k.t BETWEEN ? AND ?
ORDER BY t ASC
";

$t_test_begin = 20150101;
$t_test_end = 20150110;

$stmt_while_0 = $pdo->prepare($sql_while_0);
$stmt_while_0->execute([$t_test_begin,$t_test_end]);
$affected_rows = $stmt_while_0->rowCount();
echo "<br /> Rows Affected: ".$affected_rows."<br /><br />";

while ($row_while_0 = $stmt_while_0->fetch())
{

    $t_0 = $row_while_0['t'];

    // FIND t FROM 20 DAYS AGO  
    $sql_while = "
    SELECT t
    FROM usa_stocks_daily_bar
    WHERE 
        t < ?       
    ORDER BY t DESC
    LIMIT 20
    ";  

    $stmt_while = $pdo->prepare($sql_while);
    $stmt_while->execute([$t_0]);       
    while ($row_while = $stmt_while->fetch())
    {
        $t_20 = $row_while['t'];
    }


    // SELECT close_adj from TWO days ago
    // FIND t FROM 20 DAYS AGO
    $sql_while = "
    SELECT close, close_adj
    FROM stocks
    WHERE 
        t = ?
        AND id = ?  
    LIMIT 1
    ";


    $stmt_while = $pdo->prepare($sql_while);
    $stmt_while->execute([$t_2,$id_0]);     
    while ($row_while = $stmt_while->fetch())
    {
        $close_20 = $row_while['close'];
        $close_adj_20 = $row_while['close_adj'];
    }



}

So können Sie sehen, wo das Problem ist ... Ich benutze zwei while-Schleifen. Das funktioniert, ist aber wahnsinnig langsam. Ich bin mir sicher, dass die Lösung ungefähr so lautet:

SELECT 
    k.*, 
    y.exchange,
        (
        SELECT 
            close AS close_20
            FROM stocks k
            WHERE 
                t = (
                    SELECT z.t
                    FROM usa_stocks_daily_bar z
                    WHERE 
                        t < k.t     
                    ORDER BY z.t DESC
                    LIMIT 1 OFFSET 19                      
                    )
                AND id = k.id
            LIMIT 1     
        )        
FROM stocks k
JOIN symbols y
    ON k.id = y.id
WHERE   
    (
    y.exchange = 'NASDAQ CM' OR
    y.exchange = 'NASDAQ GM' 
    )
    AND k.t BETWEEN 20150101 AND 20150102
ORDER BY t ASC
LIMIT 2

So können Sie aus der zweiten Abfrage sehen, was ich erreichen möchte. Ich habe dies bereits versucht und eine Fehlermeldung erhalten, dass die Unterabfrage mehr als eine Zeile gezogen hat (wie Sie an der Grenze von 20 sehen können, um vor 20 Tagen zu kommen). Die Tabelle usa_stocks_daily_bar ist einfach eine Tabelle mit den angegebenen Daten -> 20150101,20150102, ...

Edit: Fuzzy hat die zweite Codestufe empfohlen. Sie kann zwar eingegeben werden, friert jedoch aus irgendeinem Grund in MySQL ein.

Ist das, weil Sie nicht zwei oder mehr Ebenen von Unterabfragen ausführen können?

Danke für Ihre Hilfe

Antworten auf die Frage(2)

Ihre Antwort auf die Frage