0

我在 MS SQL Server 上运行了类似于以下内容的 SQL:

SELECT
    CustNum,
    Name,
FROM
    Cust
    LEFT JOIN (
SELECT 
    CustNum, MAX(OrderDate) as LastOrderDate
        FROM
            Orders
        GROUP BY 
            CustNum) as Orders 
    ON Orders.CustNum = Cust.CustNum
WHERE
    Region = 1

它包含一个子查询,用于从子表中查找 MAX 记录。问题是这些表有大量的行。似乎子查询将对子表的所有行进行操作,即使由于外部查询上的 WHERE 子句实际上只需要其中的少数

有没有办法缩小内部查询的范围?像添加 WHERE 子句以仅包含外部查询中包含的记录之类的东西?就像是

WHERE CustomerOrders.CustomerNumber = Customers.CustomerNumber -- Customers from the outer query.

我怀疑这不是必需的,但我从另一个开发人员那里得到了一些回击,我想确定(我的 SQL 有点生疏)。

4

2 回答 2

1

不,如果您的统计数据等是最新的,则通常没有必要。这就是优化器的工作。如果您认为自己错过了一些快捷方式,您可以尝试使用 CROSS APPLY 运算符,但通常如果您有所有限制和统计信息,那就没问题了。

您提出的附加 WHERE 可能对您有意义,但由于它与您发布的实际查询中的任何内容都没有关联,因此它会改变结果(如果它完全有效)。如果您想对此发表评论,则需要发布表格和关系等。

最好的方法是检查执行计划,看看它是否在做任何愚蠢的事情。

于 2013-06-07T23:45:05.647 回答
1

您对子查询是正确的。它必须汇总所有数据。您可以像这样重写查询:

SELECT CustNum, Name, max(OrderDate) as LastOrderDate
FROM Cust LEFT JOIN
     Orders
     ON Orders.CustNum = Cust.CustNum
WHERE Region = 1
group by CustNum, Name

这将使 SQL 优化器选择最佳路径。

如果您知道匹配的客户非常非常少,并且您在inRegion = 1上有一个索引,则可以这样编写查询:CustNum, OrderDateOrders

select CustNum, Name,
       (select top 1 OrderDate
        from Orders o
        where Cust.CustNum = o.CustNum
        order by OrderDate desc
       ) as LastOrderDate
from Cust
Where Region = 1

我想你会得到一个非常相似的效果,使用cross apply.

顺便说一句,我不喜欢为此目的重写查询。orders但是,在这种情况下,除了汇总所有行之外,我还没有找到一个 SQL 优化器。

于 2013-06-07T23:45:44.167 回答