PDO и MySQL: подзапрос, использующий динамическое время? Способ решить, используя Join, избегая цикла while?

Пытаясь получить некоторые данные о запасах после запуска определенного набора критериев из базы данных, я получаю медленный ответ, основанный в основном на использовании динамических данных. Я вынужден войти в цикл while, чтобы разобраться в расчетах. Мне было интересно, если есть способ свести все это в один запрос, если это возможно. Ниже приведен упрощенный пример кода, который я использую, и, возможно, возможное решение.

Основная проблема заключается в том, что запрос выполняется очень медленно и выполняется со скоростью около 29 строк в секунду. (11000 строк занимает около 6 минут для запроса.)

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



}

Таким образом, вы можете увидеть, в чем проблема ... Я использовал два цикла while. Это работает, но безумно медленно. Я уверен, что решение примерно так:

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

Итак, из второго запроса видно, что я хочу выполнить. Я пытался сделать это раньше и получил сообщение о том, что подзапрос вытащил более одной строки (как вы можете видеть из предела 20, чтобы получить 20 дней назад). Таблица usa_stocks_daily_bar - это просто таблица с указанными датами -> 20150101,20150102, ...

Изменить: Fuzzy рекомендовал второй уровень кода, и он может быть введен, но по какой-то причине зависает в MySQL.

Это потому, что вы не можете сделать два или более слоя подзапросов?

Спасибо за вашу помощь.

Ответы на вопрос(1)

Ваш ответ на вопрос