T-SQL:在连接上使用内部查询时的性能

时间:2011-02-17 20:45:54

标签: tsql join

这是我正在处理的情况。我原来的查询是:

SELECT c.CustID, a.City, a.Country FROM Customers AS c
    LEFT OUTER JOIN Addresses AS a ON c.CustID = a.CustID
    WHERE c.LastName = 'Jones'

所以我想向所有姓琼的客户展示,即使没有任何地址条目的客户,也要显示相关的地址。但是如果我想在地址上使用WHERE子句但仍然显示所有客户呢?例如,如果我这样做:

SELECT c.CustID, a.City, a.Country FROM Customers AS c
    LEFT OUTER JOIN Addresses AS a ON c.CustID = a.CustID
    WHERE c.LastName = 'Jones' AND a.Country = 'United States'

我失去了任何不在美国的客户。但这不是我想要的。我希望所有客户的姓氏为“琼斯”,并且只省略不在美国的地址。这是我提出的解决方案:

SELECT  c.CustID, a.City, a.Country FROM Customers AS c
    LEFT OUTER JOIN
        (SELECT City, Country FROM Addresses
        WHERE Country = 'United States') AS a
    ON c.CustID = a.CustID
    WHERE c.LastName = 'Jones'

在这种情况下,我仍然得到所有姓琼的客户,但是看不到美国以外的地址,这就是我想要的。

这是我的问题:在第三个查询中,我假设SQL Server提取所有美国地址,然后与Customers表进行连接,这意味着很多非-Jones地址被不必要地提取。在第二个查询中,我想知道SQL Server是否仅首先获取LastName = 'Jones'的美国地址,我认为这会使查询更快。那么第三次查询的性能是否会提升?另外,无论你给出什么答案,你是否也可以在处理内部联接时评论任何差异(如果有的话),那就太好了。

谢谢!

5 个答案:

答案 0 :(得分:3)

您可以简单地将其他约束添加到left joinouter这个词是多余的,因为所有LEFTRIGHT联接都会自动OUTER ,并且所有不合格的连接都自动INNER):

SELECT 
    c.CustID, 
    a.City, 
    a.Country 

FROM Customers AS c

LEFT JOIN Addresses AS a ON c.CustID = a.CustID AND a.Country = 'United States'

WHERE c.LastName = 'Jones'

关于性能方面的问题,唯一的真正的答案是运行两个查询并比较执行计划。话虽这么说,纯粹基于连接的语法基本上更简单,并且可能会导致更简单(和更快)的执行计划。

答案 1 :(得分:3)

为加入条件的国家/地区部分进行测试。

SELECT c.CustID, a.City, a.Country 
    FROM Customers AS c
        LEFT OUTER JOIN Addresses AS a 
            ON c.CustID = a.CustID
                AND a.Country = 'United States'
    WHERE c.LastName = 'Jones'

答案 2 :(得分:1)

您的查询的一种更简单的形式是:

SELECT c.CustID, a.City, a.Country
FROM Customers AS c     
LEFT OUTER JOIN Addresses AS a 
    ON c.CustID = a.CustID  AND a.Country = 'United States'     
WHERE c.LastName = 'Jones' 

为了查看它是否比你的查询更好,我建议查看执行计划。

您的查询2不起作用的原因是将条件放在where子句中,您实际上已将其作为内连接。

答案 3 :(得分:1)

SELECT c.CustID, a.City, a.Country
  FROM Customers AS c LEFT OUTER JOIN Addresses AS a ON c.CustID = a.CustID
 WHERE c.LastName = 'Jones'
   AND (a.Country = 'United States' OR a.Country IS NULL)

答案 4 :(得分:0)

在您查看效果时,您可能想尝试使用APPLY运算符:

SELECT c.CustID, a.City, a.Country  
FROM Customers AS c 
    OUTER APPLY 
    (
        SELECT City, Country
        FROM Addresses  
        WHERE c.CustID = a.CustID 
            AND a.Country = 'United States' 
    ) AS a
WHERE c.LastName = 'Jones'

有时,当右边的表很大,并且优化器认为将返回超过5%左右的记录时,您将获得表扫描和与外连接的哈希匹配。但是,索引查找和嵌套循环会更快。我在许多情况下都使用了APPLY运算符来显着提高性能。

我不知道你的情况会如何,但是可能值得比较执行时间和计划,看看哪个最好。