2017-08-03 117 views
3

所以首先我的MySQL表中這樣定義:MySQL的 - 花費過多時間來執行查詢

訂單(333000+記錄)

orders_id(PK), 
customerName, 
CompanyName, 
Status, 
shipping_no, 
shipping_module, 
tracking_no, 
orders_status, 
date_purchased.. 

ORDER_STATUS(70條記錄)

orders_status_id(pk), 
language_id, 
orders_status_name 

orders_status_history(2220000+ r ecords)

`orders_status_history_id` int(11) 
    `orders_id` int(11) 
    `orders_status_id` int(5) 
    PRIMARY KEY (`orders_status_history_id`) 

orders_status_history表包含每個訂單

`orders_status_id` int(11) 
    `orders_status_name` varchar(32) 
    PRIMARY KEY (`orders_status_id`,`language_id`) 

那麼我試圖得到的是不同的狀態,下面這三個選項描述:

  1. 訂單必須有shipping_module pickup_pickup或pickup2_pickup2
  2. orders_status_history.orders_status_id必須有以下狀態7,21,34,40
  3. orders_status_history.orders_status_id不得有下列狀態33,53

說明問題: 假設有10項目,和他們有過如下的狀態,在一些時間在其一生中:

  1. [7,34,41,48]
  2. [20,40,34,57,14,25]
  3. [53,7,40,5]
  4. [41,25,4]
  5. [1,2,3,4]
  6. [34,4,33,53,7]
  7. [4,21,31,7,8]
  8. 我想
  9. [78,15,45,40]
  10. [53,40,31,21,7]
  11. [33,74,54,7,22]

所以訂單提取是1,2,7,8-因爲這個訂單包含7,31,21或40,而不是53,33

我曾嘗試以下查詢:

1)

SELECT * 
FROM orders AS o, orders_status_history AS osh 
WHERE (
     o.shipping_module LIKE '%pickup_pickup%' 
     OR o.shipping_module LIKE '%pickup2_pickup2%' 
    ) 
AND o.orders_id = osh.orders_id 
AND osh.orders_status_id 
IN (7, 21, 31, 40) AND osh.orders_status_id 
NOT IN (33, 53) 

此查詢工作正常的表現,但它得到的所有結果(1200條記錄),但它並沒有過濾3選項

2 。)

SELECT * 
FROM orders AS o, orders_status_history AS osh 
WHERE (
     o.shipping_module LIKE '%pickup_pickup%' 
     OR o.shipping_module LIKE '%pickup2_pickup2%' 
    ) 
AND o.orders_id = osh.orders_id 
AND osh.orders_status_id IN (7, 21, 31, 40) 
AND osh.orders_status_id != 33 
AND osh.orders_status_id != 53 

它的工作原理也如以前,didnt過濾器3選項

3)

SELECT * 
FROM orders AS o, orders_status_history AS osh 
WHERE (
     o.shipping_module LIKE '%pickup_pickup%' 
     OR o.shipping_module LIKE '%pickup2_pickup2%' 
    ) 
AND o.orders_id = osh.orders_id 
AND osh.orders_status_id IN (7, 21, 31, 40) 
AND osh.orders_status_id NOT IN (
           SELECT so.orders_id 
           FROM orders AS so, orders_status_history AS sosh 
           WHERE (
             so.shipping_module LIKE '%pickup_pickup%' 
             OR so.shipping_module LIKE '%pickup2_pickup2%' 
             ) 
           AND sosh.orders_status_id != 33 
          ) 

這個查詢花費了太多的時間來執行,並沒有EXCUTE

4 )

SELECT * 
FROM orders AS o, orders_status_history AS osh 
WHERE (
     o.shipping_module LIKE '%pickup_pickup%' 
     OR o.shipping_module LIKE '%pickup2_pickup2%' 
    ) 
AND o.orders_id = osh.orders_id 
AND osh.orders_status_id = 7 
AND osh.orders_status_id = 21 
AND osh.orders_status_id = 31 
AND osh.orders_status_id = 40 
AND osh.orders_status_id != 33 
AND osh.orders_status_id != 53 

該查詢當先過於查詢沒有過濾選項3

所以後來我用PHP

$sql = "SELECT o.orders_id, osh.orders_status_history_id 
     FROM 
      orders AS o, 
      orders_status_history AS osh 
     WHERE ( 
      o.shipping_module LIKE '%pickup_pickup%' 
      OR o.shipping_module LIKE '%pickup2_pickup2%' 
      ) 
     AND o.orders_id = osh.orders_id 
     AND osh.orders_status_id IN (7, 21, 31, 40) 
     AND osh.orders_status_id != 33 
     AND osh.orders_status_id != 53"; 
$sql = mysql_query($sql); 
while ($row = mysql_fetch_array($sql)){ 
    $row["orders_id"]); 
    if(getOrderStatus($row["orders_id"])) 
     echo "<br/>".$row["orders_id"]; 
} 

function getOrderStatus($order){ 
    $sql = "SELECT orders_status_id FROM orders_status_history WHERE orders_id = ".$order; 
    echo "<br/> Sql Query : ".$sql; 
    $sql = mysql_query($sql); 
    while ($status  = mysql_fetch_array($sql)) 
     if((int)$status["orders_status_id"] == 33 || (int)$status["orders_status_id"] == 53) 
      return false; 
    return true; 
} 

此代碼是花費過多時間超過30m嘗試過。我set_time_limit(0);

注:我只能使用Mysql_ *因爲我們的PHP版本是4.9

+2

除了PHP 4.9真的過時了(你應該提醒你的老闆升級),你有沒有運行'在你的查詢中解釋......'爲表格設置了什麼樣的指數? – Paul

+2

'osh.orders_status_id IN(7,21,31,40)AND osh.orders_status_id NOT IN(33,53)''沒有任何意義,就好像某物是(7,21,31,40)而不是定義不(33,53)。其他查詢以不同的形式呈現。那麼你確定你仍然在33,53在你的resluts獲得記錄? – pawel7318

+0

我從來沒有見過任何人使用PHP 4年...這是嚴重過時的,完全不安全。此外,它不應該影響查詢..因爲@ paul提到在查詢前面使用'EXPLAIN'。它應該,解釋它做了什麼,它使用了什麼索引......它可能缺少一些 –

回答

2

這裏有一個方法來獲取訂單符合條件:

SELECT o.orders_id 
FROM orders o JOIN 
    orders_status_history osh 
    ON o.orders_id = osh.orders_id 
WHERE (o.shipping_module LIKE '%pickup_pickup%' OR 
     o.shipping_module LIKE '%pickup2_pickup2%' 
    ) AND 
     osh.orders_status_id IN (7, 21, 31, 40, 33, 53) 
GROUP BY o.orders_id 
HAVING SUM(osh.orders_status_id IN (33, 53)) = 0; 

WHERE只選擇你關心的狀態。 HAVING確保你沒有最後兩個。

如果你想在訂單或訂單行的細節,那麼你就需要加入這些表回。