2016-10-03 36 views
1

我有一個查詢從product表(第一選擇)獲取產品說明,然後將其減去以下子查詢語句以獲得no。剩餘庫存的:使用多個連接優化SQL查詢。需要關於技術快速有效地檢索數據的建議

每個產品的-sum inventory表(第二)

每個產品的-sum在sales_detail表(第三)

每個-sum出售產品轉移到另一個分支stock_transfer表(第4)

-每個產品的總和損壞damaged_product表(第5個)

問題是每次查詢加載時,它會全部搜索所有4個表以獲得quantity列的總和。隨着時間的推移,更多的記錄被存儲,查詢將變得更慢。有什麼建議麼?

SELECT p.Id,p.Product_Name Product,p.Description, c.Category_Name Category,sc.Subcategory_Name Subcategory,s.Supplier_Name Supplier, p.Selling_Price `Unit Price`,i.Stocks,s.Sales, i.Stocks - IFNULL(s.Sales, 0) - IFNULL(t.Transfer, 0) - IFNULL(d.Damage, 0) AS Remaining 

FROM (SELECT Id, Product_Name, Description, Selling_Price, Category_Id, Subcategory_Id, Supplier_Id  FROM product WHERE enable_flag = 1) p 

LEFT OUTER JOIN(SELECT product_id, COALESCE(SUM(quantity), 0) AS Stocks 
       FROM inventory 
       WHERE enable_flag = 1 GROUP BY product_id) i ON p.Id = i.product_id 

LEFT OUTER JOIN(SELECT product_id, COALESCE(SUM(quantity), 0) AS Sales 
       FROM sales_detail 
       WHERE enable_flag = 1 GROUP BY product_id) s USING(product_id) 

LEFT OUTER JOIN(SELECT product_id, COALESCE(SUM(transfer_quantity), 0) AS Transfer 
       FROM stock_transfer 
       WHERE enable_flag = 1 GROUP BY product_id) t USING(product_id) 

LEFT OUTER JOIN(SELECT product_id, COALESCE(SUM(damaged_quantity), 0) AS Damage 
       FROM damaged_product 
       WHERE enable_flag = 1 GROUP BY product_id) d USING(product_id) 

JOIN Category c ON p.Category_Id=c.Id 

JOIN Subcategory sc ON p.Subcategory_Id=sc.Id 

JOIN Supplier s ON p.Supplier_Id=s.Id; 
+1

索引列有很大的影響關於查詢性能。 是否在涉及查詢的所有表中索引了內部和外部鍵? –

+0

我相信MySql中的主鍵在創建時會自動建立索引,對於外鍵也一樣。我需要檢查'JOIN'子句中的所有'WHERE'語句是否都被索引。由於 –

+0

我指的是類似在這個例子中爲user_id,沒有索引的外鍵列: CREATE TABLE MyGuests( \t ID INT(6)UNSIGNED AUTO_INCREMENT PRIMARY KEY, \t USER_ID INT NOT NULL, \t姓VARCHAR( 30)NOT NULL, \t姓氏VARCHAR(30)NOT NULL, \t電子郵件VARCHAR(50), \t reg_date TIMESTAMP ) 此外,這裏是一個類似的帖子,可能會給你一個提示。 http://stackoverflow.com/questions/9330204/optimizing-mysql-query-with-sum-date-range-and-group-by –

回答

1

您正在強制在子表上創建一個完整的groupby,這是不必要的。

SELECT Id, Product_Name Product, Description, Category_Name Category, Subcategory_Name Subcategory, 
Supplier_Name Supplier, Selling_Price 'Unit Price', 
Stocks, Sales, Stocks - Sales - Transfer - Damage AS Remaining 
FROM  
(select p.*, sc.Subcategory_Name, s.Supplier_Name, 
IFNULL((SELECT SUM(quantity) FROM inventory WHERE enable_flag = 1 and product_id = p.Id),0) as Stocks, 
IFNULL((SELECT SUM(quantity) FROM sales_detail WHERE enable_flag = 1 and product_id = p.Id),0) as Sales, 
IFNULL((SELECT SUM(transfer_quantity) FROM stock_transfer WHERE enable_flag = 1 and product_id = p.Id),0) as Transfer, 
IFNULL((SELECT SUM(damaged_quantity) FROM damaged_product WHERE enable_flag = 1 and product_id = p.Id),0) as Damage 
FROM product p 
JOIN Category c ON p.Category_Id=c.Id 
JOIN Subcategory sc ON p.Subcategory_Id=sc.Id 
JOIN Supplier s ON p.Supplier_Id=s.Id 
WHERE enable_flag = 1 
) p 

而且ofcourse,你應該確保你有product_id指標上inventorysales_detailstock_transferdamaged_product,加上Category_IdCategorySubcategory_IdSubcategory,最後Supplier_IdSupplier

+0

我想我仍然需要'GROUP BY'來合計每個產品ID。爲了澄清,將每個產品的總和分組的工作是由單獨的'和product_id = p.Id'完成的? –

+1

如果您關心每個產品的所有值,您只需要一組。例如如果您想比較目前的產品損壞貨物與損壞貨物的平均數量。但是在這裏你只關心每個單獨的產品,因此普通的正常選擇子查詢就沒有問題。 (請注意,select子查詢總是外連接) – Cine

+0

順便說一句,您的第一個'IFNULL'缺少一個左括號,並且在最後一個'WHERE'子句之前有分號。非常感謝您的幫助,我會在測試查詢後回覆您:) –