这是我正在处理的情况。我原来的查询是:
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'
的美国地址,我认为这会使查询更快。那么第三次查询的性能是否会提升?另外,无论你给出什么答案,你是否也可以在处理内部联接时评论任何差异(如果有的话),那就太好了。
谢谢!
答案 0 :(得分:3)
您可以简单地将其他约束添加到left join
(outer
这个词是多余的,因为所有LEFT
和RIGHT
联接都会自动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运算符来显着提高性能。
我不知道你的情况会如何,但是可能值得比较执行时间和计划,看看哪个最好。