2016-04-26 22 views
0

在試圖從數據庫中觸發一定數量的標準後,下拉一些股票數據時,我收到的反應很慢,主要是基於使用動態數據。我不得不進入一個while循環來計算。我想知道如果可能的話,是否有辦法將這一切都彙總成一個查詢。以下是我正在使用的代碼的簡化示例,也許是一種可能的解決方案。PDO&MySQL:使用動態時間的子查詢?通過避免while循環來解決使用Join的方法?

主要的問題是查詢速度很慢,而且每秒只能以大約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,...

編輯: 模糊推薦第二層代碼,它能夠進入,但凍結在MySQL的一些原因。

這是因爲你不能做兩層或多層的子查詢?

感謝您的幫助。

+0

您可以發佈您的架構和一些樣品輸入+輸出數據? – FuzzyTree

+0

它通過具有日常數據的股票表逐行運行。它會檢查特定的指標:在這種情況下,我們正在尋找20天前的close和close_adj,希望能夠將這些指標變成單個查詢來加快速度。 – Aoi

回答

0

就快,你似乎有一個太多「OR」

WHERE 
    (
    y.exchange = 'NASDAQ CM' OR 
    y.exchange = 'NASDAQ GM' OR 
    ) 
    AND k.t BETWEEN 20150101 AND 20150110 

應該是...

WHERE 
    (
    y.exchange = 'NASDAQ CM' OR 
    y.exchange = 'NASDAQ GM' 
    ) 
    AND k.t BETWEEN 20150101 AND 20150110 
+0

更新w/new錯誤,並重新編寫代碼。 – Aoi

相關問題