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.
Это потому, что вы не можете сделать два или более слоя подзапросов?
Спасибо за вашу помощь.