2013-04-04 48 views
0

以下是我需要優化的查詢。如何使用嵌套連接優化此mysql查詢?

SELECT 
     UPPER(IFNULL(op.supplier_payment_method,s.default_payment_method)) AS Payment_Method, 
     op.supplier_payment_date AS Payment_Date, 
     Date_format(IFNULL(op.supplier_payment_date,op.ship_date),'%M %Y') AS Payment_Month, 
     s.supplier_name AS Farm, 
     op.sub_order_id AS Order_num, 
     Date_format(op.ship_date,'%b-%d-%Y') AS Ship_Date, 
     op.farm_credit AS Farm_Credit, 
     op.credit_memo AS Credit_Memo, 
     op.credit_description AS Credit_Description, 
     opb.boxes AS Box_Type, 
     CONCAT('$',FORMAT(op.box_charge,2)) AS Box_Charge, 
     op.invoice_num AS Invoice_num, 
     CONCAT('$',FORMAT(op.invoice_amt,2)) AS Invoice_Amt, 
     CONCAT('$',FORMAT(op.total_invoice_amt,2)) AS Total_Invoice_Amt, 
     CONCAT(op.UM_qty,' ',op.UM_type) AS St_Bu_Qty, 
     op.PO_Product_Name AS Invoice_desc, 
     CONCAT('$',FORMAT((op.price_um*op.um_qty),2)) AS Cost_product_cms, 
     op.supplier_invoice_note AS Supplier_Invoice_Notes, 
     CONCAT('$',FORMAT(op.cms_invoice_cost,2)) AS CMS_Invoice_diff, 
     CONCAT('$',FORMAT(op.total_farm_cost,2)) AS Farm_Cost 
    FROM 
     orders_products op 
     INNER JOIN 
      suppliers s ON s.supplier_id = op.supplier_name 
     LEFT JOIN 
      (
       SELECT 
        sub_order_id, 
        GROUP_CONCAT(CONCAT(box_type_qty,' ',bo.box_option_name) SEPARATOR ', ') AS boxes 
       FROM 
        order_products_boxes opb 
        INNER JOIN box_options bo ON bo.id=opb.box_type_id 
       GROUP BY 
        opb.sub_order_id 
      ) opb ON opb.sub_order_id = op.sub_order_id 
    WHERE 
     op.order_active=0 
     AND op.ship_date>='2013-03-01' 
     AND op.ship_date<='2013-04_01' 
    ORDER BY op.ship_date DESC 

正如您所看到的,查詢包含4個表格,每個表格包含大約20k-30k行。因此,只要我在子查詢中添加,查詢變得異常緩慢。大約需要1.5分鐘才能獲取500行記錄。有沒有辦法在單個查詢中加快速度?

+0

爲什麼你有一個SELECT語句作爲JOIN的說法?查詢結果中不會返回此SELECT中的信息。 – Richard 2013-04-04 12:24:28

+0

在表'order_products'和'suppliers'之間的第一個'ON'條件中添加'op.order_active = 0'條件,還有一條建議嘗試在where子句中使用'BETWEEN'子句進行日期比較...... – Meherzad 2013-04-04 12:26:07

+0

@Richard這是因爲我需要做一個GROUP_CONCAT來獲取所需的結果,而且我不能在實際的結果集中這樣做,因爲在第一個INNER JOIN中,我將最終得到一行 – Bluemagica 2013-04-04 12:28:11

回答

0

你的左連接查詢該預會連接子中的選項首先查詢整個數據庫,那麼只有加入到那些你限制了外WHERE子句的標準之內。這可能會多一點努力,但將相同的外部標準拉入內部查詢應該會有很大的幫助。至於在每一行的基礎上做一個字段級的sql選擇可能是一個性能殺手。

您應該只需要在「FROM」子句更改...

from 
    orders_products op 
     INNER JOIN suppliers s 
     ON op.supplier_name = s.supplier_id 
     LEFT JOIN 
     (SELECT 
       opb2.sub_order_id, 
       GROUP_CONCAT(CONCAT(box_type_qty,' ',bo.box_option_name) SEPARATOR ', ') AS boxes 
       FROM 
       orders_products op2 
        JOIN order_products_boxes opb2 
         on op2.sub_order_id = opb2.sub_order_id 
         INNER JOIN box_options bo 
          ON opb2.box_type_id = bo.id 
       WHERE 
        op2.order_active = 0 
       AND op2.ship_date >= '2013-03-01' 
       AND op2.ship_date <= '2013-04_01' 
       GROUP BY 
       opb2.sub_order_id ) opb 
     ON op.sub_order_id = opb.sub_order_id 
WHERE 
     op.order_active = 0 
    AND op.ship_date >= '2013-03-01' 
    AND op.ship_date <= '2013-04_01' 
+0

謝謝你的工作就像一個魅力....我在想用某種方式使用訂單ID限制來加快速度,但我從來沒有想過在子查詢中執行相同的事情 – Bluemagica 2013-04-04 13:00:33

0
SELECT 
    UPPER(IFNULL(op.supplier_payment_method,s.default_payment_method)) AS Payment_Method, 
    op.supplier_payment_date AS Payment_Date, 
    Date_format(IFNULL(op.supplier_payment_date,op.ship_date),'%M %Y') AS Payment_Month, 
    s.supplier_name AS Farm, 
    op.sub_order_id AS Order_num, 
    Date_format(op.ship_date,'%b-%d-%Y') AS Ship_Date, 
    op.farm_credit AS Farm_Credit, 
    op.credit_memo AS Credit_Memo, 
    op.credit_description AS Credit_Description, 
    (
      SELECT 
       GROUP_CONCAT(CONCAT(box_type_qty,' ',bo.box_option_name) SEPARATOR ', ') 
      FROM 
       order_products_boxes opb 
       INNER JOIN box_options bo ON bo.id=opb.box_type_id 
      GROUP BY 
       opb.sub_order_id 
     ) AS Box_Type, 
    CONCAT('$',FORMAT(op.box_charge,2)) AS Box_Charge, 
    op.invoice_num AS Invoice_num, 
    CONCAT('$',FORMAT(op.invoice_amt,2)) AS Invoice_Amt, 
    CONCAT('$',FORMAT(op.total_invoice_amt,2)) AS Total_Invoice_Amt, 
    CONCAT(op.UM_qty,' ',op.UM_type) AS St_Bu_Qty, 
    op.PO_Product_Name AS Invoice_desc, 
    CONCAT('$',FORMAT((op.price_um*op.um_qty),2)) AS Cost_product_cms, 
    op.supplier_invoice_note AS Supplier_Invoice_Notes, 
    CONCAT('$',FORMAT(op.cms_invoice_cost,2)) AS CMS_Invoice_diff, 
    CONCAT('$',FORMAT(op.total_farm_cost,2)) AS Farm_Cost 
FROM 
    orders_products op 
    INNER JOIN 
     suppliers s ON s.supplier_id = op.supplier_name 
    LEFT JOIN 

       order_products_boxes opb (
       INNER JOIN box_options bo ON bo.id=opb.box_type_id 
     ) opb ON opb.sub_order_id = op.sub_order_id 
WHERE 
    op.order_active=0 
    AND op.ship_date>='2013-03-01' 
    AND op.ship_date<='2013-04_01' 
ORDER BY op.ship_date DESC 
+0

問題是需要放在子查詢中的group_concat。基本上,箱子名稱和盒子名稱都是盒子表格,每個產品映射表格可以將盒子按ID映射到盒子的順序和數量,從而將盒子名稱和數量放在一起,然後顯示在同一個字段中在結果集中,我必須做一個group_concat – Bluemagica 2013-04-04 12:31:04

+0

得到這個錯誤:你的SQL語法有錯誤;檢查與您的MySQL服務器版本相對應的手冊,以便在第36行的'(INNER JOIN box_options bo ON bo.id = opb.box_type_id)o'處使用正確的語法 – Bluemagica 2013-04-04 12:43:56

+0

在LEFT JOIN中的ON之前刪除opb。 – Richard 2013-04-04 12:48:25