【问题标题】:Optimize query with multiple subquery joins使用多个子查询连接优化查询
【发布时间】:2016-08-03 13:13:38
【问题描述】:

我有一个查询,它从product 表(第一次选择)中获取产品描述,然后将其减去以下子查询语句以获得编号。剩余库存:

-inventory 表中购买的每种产品的总和(第二个)

-sales_detail 表中销售的每种产品的总和(第 3 个)

-转移到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;

【问题讨论】:

    标签: mysql sql join subquery left-join


    【解决方案1】:

    使用子查询会阻止使用索引,这会降低查询速度。我建议这样的查询:

    SELECT p.*, sc.Subcategory_Name as Subcategory, s.Supplier_Name as Supplier,
           p.Selling_Price as `Unit Price`,
           (SELECT COALESCE(SUM(quantity), 0) 
            FROM inventory i
            WHERE s.enable_flag = 1 AND s.product_id = p.product_id
           ) as stocks,
           (SELECT COALESCE(SUM(quantity), 0) 
            FROM sales_detail sd
            WHERE i.enable_flag = 1 AND i.product_id = p.product_id
           ) as sales,
           (SELECT COALESCE(SUM(tansferquantity), 0) 
            FROM stock_transfer st
            WHERE st.enable_flag = 1 AND st.product_id = p.product_id
           ) as transfers,
           (SELECT COALESCE(SUM(damaged_quantity), 0) 
            FROM damage d
            WHERE d.enable_flag = 1 AND d.product_id = p.product_id
           ) as damaged
    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 p.enable_flag = 1;
    

    为了提高性能,基础表需要(product_id, enable_flag, quantity) 上的索引。 MySQL 可以在相关子查询中使用索引进行聚合。

    我知道您也有计算值。您可能需要在外部查询中进行这些计算,并受到子查询的额外实现的影响。

    【讨论】:

    • 感谢@Gordon Linoff 的提示!我会试试这个,一旦我完成测试就会把它标记为接受
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 2010-11-06
    • 2020-04-30
    相关资源
    最近更新 更多