PDO y MySQL: ¿Subconsulta usando tiempo dinámico? ¿Manera de resolver usando Join evitando el bucle while?

Al tratar de extraer algunos datos de stock después de que se activa un cierto conjunto de criterios desde una base de datos, obtengo una respuesta lenta basada principalmente en el uso de datos dinámicos. Me he visto obligado a entrar en un ciclo while para anular los cálculos. Me preguntaba si hay una manera de resumir todo esto en una sola consulta si es posible. El siguiente es un ejemplo simplificado del código que estoy usando, y tal vez una posible solución.

El principal problema es que la consulta es súper lenta y solo va a una velocidad de aproximadamente 29 filas por segundo. (11000 filas tardan aproximadamente 6 minutos en consultarse).

$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'];
    }



}

Para que pueda ver dónde está el problema ... Estoy usando dos bucles while. Esto funciona, pero es increíblemente lento. Estoy seguro de que la solución es algo como esto:

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

Entonces pueden ver en la segunda consulta lo que quiero lograr. Intenté esto antes y recibí un error que decía que la subconsulta extrajo más de una fila (como puede ver en el límite 20, para obtener hace 20 días). La tabla usa_stocks_daily_bar es simplemente una tabla con las fechas enumeradas -> 20150101,20150102, ...

Editar: Fuzzy recomendó el segundo nivel de código, y se puede ingresar, pero se congela en MySQL por alguna razón.

¿Es esto porque no puedes hacer dos o más capas de subconsultas?

Gracias por tu ayuda.

Respuestas a la pregunta(1)

Su respuesta a la pregunta