为什么Adventure Works 2017下两条SQL Server查询结果不一致?
两个SQL查询结果差异原因解释
使用的数据库为Adventure Works 2017,两条查询结果不同的核心原因是JOIN的执行顺序与作用范围被括号改变,逻辑完全不同:
查询1执行逻辑
select c.CustomerID, c.FirstName, c.EmailAddress, a.AddressID as addrId, addr.AddressLine1 as address from [AdventureWorksLT2017].[SalesLT].[Customer] c left join ( [AdventureWorksLT2017].[SalesLT].[CustomerAddress] a inner join [AdventureWorksLT2017].[SalesLT].[Address] addr on addr.AddressID = a.AddressID ) on c.CustomerID=a.CustomerID where c.EmailAddress = 'orlando0@adventure-works.com';
- 首先执行括号内的INNER JOIN:先对
CustomerAddress和Address做内连接,只有同时存在两张表的关联记录才会被保留,过滤掉所有没有对应地址的客户地址关联记录。 - 再将上述得到的关联地址结果集,和
Customer表做LEFT JOIN:符合WHERE条件的客户记录一定会被保留,不管有没有匹配到关联地址结果,没有匹配到的地址相关字段返回NULL。
查询2执行逻辑
select c.CustomerID, c.FirstName, c.EmailAddress, a.AddressID as addrId, addr.AddressLine1 as address from [AdventureWorksLT2017].[SalesLT].[Customer] c left join [AdventureWorksLT2017].[SalesLT].[CustomerAddress] a on a.CustomerID = c.CustomerID inner join [AdventureWorksLT2017].[SalesLT].[Address] addr on addr.AddressID = a.AddressID where c.EmailAddress = 'orlando0@adventure-works.com';
- 第一步先执行
Customer和CustomerAddress的LEFT JOIN:符合WHERE条件的客户记录先被保留,没有关联的客户地址记录时,a.AddressID等字段返回NULL。 - 第二步将上述结果集和
Address做INNER JOIN:内连接要求a.AddressID = addr.AddressID,上一步结果中所有a.AddressID为NULL、或者a.AddressID在Address表中找不到匹配的记录都会被直接过滤,最终结果仅保留同时有客户地址关联、且地址记录存在的客户。
差异总结
如果查询的客户没有关联的CustomerAddress记录,或者关联的地址不存在于Address表中:
- 查询1会返回该客户的基础信息,地址相关字段为NULL
- 查询2会直接过滤掉该客户,结果中无对应记录
内容的提问来源于stack exchange,提问作者Saurav Sehgal
相关产品推荐
相关产品推荐

