2013-04-04 2 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 строк. Поэтому, как только я добавляю в подзапрос, запрос становится чрезвычайно медленным. Для получения всего 500 строк записи требуется около 1,5 минут. Есть ли способ ускорить процесс в рамках одного запроса?

+0

Почему у вас есть ЗЕЬЕСТ в качестве аргумента JOIN? Информация в этом SELECT не будет возвращена в результатах запроса. – Richard

+0

Добавить условие 'op.order_active = 0' в первом состоянии' ON' между таблицей 'order_products' и' поставщиками'. Еще одно предложение попробуйте использовать предложение BETWEEN для сравнения даты в предложении where ... – Meherzad

+0

@Richard Это потому, что мне нужно сделать GROUP_CONCAT, чтобы получить желаемый результат, и я не могу сделать это в фактическом наборе результатов, так как в итоге у меня будет только одна строка – Bluemagica

ответ

0

Ваш левый присоединиться запрос, пре-сцепляются опции суб-окно запрашивает всю базу данных, а затем только присоединяется к тем, которые находятся в пределах критериев вы предельными для внешнего ИНЕКЕ. Это может быть немного больше усилий, но потянуть те же внешние критерии в ваш внутренний запрос, должно значительно помочь. Что касается выполнения sql-select на уровне поля на каждой строке, может быть убийцей производительности.

Вы должны только изменить на «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

Спасибо, что работали как обаяние .... Я думал о том, чтобы каким-то образом использовать ограничение идентификатора заказа, чтобы ускорить работу, но я никогда не думал о том, чтобы выполнить ту же самую вещь в подзапросе – Bluemagica

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 должен быть помещен в подзапрос. В принципе, есть таблица ящиков с именем окна и таблицей сопоставления продуктов для сопоставления поля по идентификатору с порядком и количеством этого поля, поэтому, чтобы получить имя и количество полей вместе, а затем отобразить их в одном поле в наборе результатов, я должен сделать group_concat – Bluemagica

+0

Получил эту ошибку: У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с ним (INNER JOIN box_options bo ON bo.id = opb.box_type_id) o 'в строке 36 – Bluemagica

+0

Удалите опцию перед ВКЛЮЧЕНИЕМ в ЛЕВОМ СОЕДИНЕНИИ. – Richard

Смежные вопросы