如何优化这个嵌套的 SQL 查询

Posted

技术标签:

【中文标题】如何优化这个嵌套的 SQL 查询【英文标题】:How to optimize this nested SQL query 【发布时间】:2012-11-11 13:04:22 【问题描述】:

这是数据库架构:

[编辑]

我将在下面的查询中描述我正在做什么:

最内层查询:选择所有满足WHERE条件的saleIds

中间查询:选择属于saleId的所有productIds

最外层查询SUMproducts.cost 并选择vendors.name

这是我想出的 SQL 查询:

SELECT vendors.name AS Company
, SUM(products.cost) AS Revenue
FROM
    products
    INNER JOIN sold_products
        ON (products.productId = sold_products.productId)
    INNER JOIN vendors
    ON (products.vendorId = vendors.vendorId)
            WHERE sold_products.productId IN (
                    SELECT sold_products.productId
                    FROM
                        sold_products
                    WHERE sold_products.saleId IN (
                            SELECT sales.saleId     
                            FROM
                                markets
                                INNER JOIN vendors
                                ON (markets.vendorId = vendors.vendorId)
                                INNER JOIN sales_campaign
                                ON (sales_campaign.marketId = markets.marketId)
                                INNER JOIN packet_headers
                                ON (sales_campaign.packetHeaderId = packet_headers.packetHeaderId)
                                INNER JOIN packet_details
                                ON (packet_details.packetHeaderId = packet_headers.packetHeaderId)
                                INNER JOIN sales
                                ON (sales.packetDetailsId = packet_details.packetDetailsId)
                            WHERE vendors.customerId=60
                            )
                    )
GROUP BY Company
ORDER BY Revenue DESC;

对优化有帮助吗?

【问题讨论】:

EXPLAIN 告诉你什么?你试过什么? @Bohemian:EXPLAIN给我看了一张详细的表格,但我怕我不明白是什么意思.. 【参考方案1】:

由于您只是使用内部联接,因此您通常将查询简化为如下所示:

SELECT  ve.name     AS Company
,       SUM(pr.cost) AS Revenue
FROM    products        pr
,       sold_products   sp
,       vendors         ve
,       markets         ma
,       sales_campaign  sc
,       packet_headers  ph
,       packet_details  pd
,       sales           sa
Where pr.productId = sp.productId
And   pr.vendorId  = ve.vendorId
And   ve.vendorId  = ma.vendorId
And   sc.marketId = ma.marketId
And   sc.packetHeaderId = ph.packetHeaderId
And   pd.packetHeaderId = ph.packetHeaderId)
And   sa.packetDetailsId = pd.packetDetailsId
And   ve.customerId = 60
GROUP BY ve.Company
ORDER BY pr.Revenue DESC;

请尝试这是否可行,如果它更快,请告诉我。

【讨论】:

Heiz Matchinger:这正是我之前所做的,但结果完全错误。此查询将返回所有产品的SUM(products.cost),无论它们是否已售出...... 您是否检查过它是否真的是所有产品,或者它是否只是多次求和一个产品?!加入到 sold_products 它不能对所有产品求和!查看没有 SUM 的查询 => 结果是什么? 是的,它确实是该供应商所有产品的总和;不仅仅是已售出的总和.. 尝试简化查找错误: SELECT ve.name AS Company , SUM(pr.cost) AS Revenue FROM products pr , sold_products sp ,vendors ve where pr.productId = sp.productId And pr .vendorId = ve.vendorId And ve.customerId = 60 GROUP BY ve.Company ORDER BY pr.Revenue DESC; 哇,效果很好!也是瞬间!!谢谢:)

以上是关于如何优化这个嵌套的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JOINS 和嵌套 SELECT 优化此 SQL 查询?

如何优化执行嵌套在 group-by 子句中的计数的 SQL 查询?

如何重写这个嵌套的 SQL 查询以使其更快? [关闭]

使用算术运算优化 MySQL 嵌套选择

如何在 Linq 中编写嵌套的 Sql 查询 [关闭]

如何优化这个 sql 查询(内连接)