现在的位置: 首页 > 综合 > 正文

《SQL Server 2005技术内幕:T-SQL查询》上的一处错误

2012年04月20日 ⁄ 综合 ⁄ 共 1128字 ⁄ 字号 评论关闭

SQL Server 2005技术内幕:T-SQL查询》一书的第7章,“使用TOPApply解决常见问题”一节中,介绍了多种方式获得每个销售员的最新订单。

其中第三种方式是这样的。书上只是说这是个“糟糕计划”,其实是糟糕T-SQL代码造成的。而这个方案其实可以优化成为作者给出的三个用于SQL Server 2000的方案中最好的一个。

SELECT OrderID, CustomerID, E.EmployeeID, OrderDate, RequiredDate
FROM dbo.Employees AS E
   
JOIN dbo.Orders AS O1
     
ON OrderID IN
       (
SELECT TOP(3) OrderID
        
FROM dbo.Orders AS O2
        
WHERE O2.EmployeeID = E.EmployeeID
        
ORDER BY OrderDate DESC, OrderID DESC);

 

有看出问题吗?再看看它上面的图。


注意第二个
Nested Loops上有一个感叹号。知道是什么原因了吗?如果还没有看出问题的话,可以参考书上271页,讲述联接的部分。 

这个警告是“没有联接谓词”,说明白些,就是指上面的SQL代码中的JOIN没有相关的ON子句。注意不是说没有ON子句,是说没有与JOIN相关的ON子句。 

没有ON子句的JOIN就变成了CROSS JOIN。能不慢吗? 

大家有兴趣可以自己想一想如何优化这个SQL。我在AdventureWorks上做的测试,运行速度提高近100倍。 

答案如下: 

SELECT OrderID, CustomerID, E.EmployeeID, OrderDate, RequiredDate
FROM dbo.Employees AS E
   
JOIN dbo.Orders AS O1
     
ON O1.EmployeeID = E.EmployeeID AND OrderID IN
       (
SELECT TOP(3) OrderID
        
FROM dbo.Orders AS O2
        
WHERE O2.EmployeeID = E.EmployeeID
        
ORDER BY OrderDate DESC, OrderID DESC);

其执行计划如下图所示:

书中有错误是很正常的。读一本书,其实可以把找出错误的个数,作为衡量书是不是真正读懂的一个标准。我自己读书就有一个习惯,把书的第一个空白页当勘误表。一般发现翻译错误、字词遗漏什么的也不值当发上来,不过这个错误感觉就比较严重了。

抱歉!评论已关闭.