我有三个表:
命令
顾客
公司介绍
我想选择所有订单,无论是否有客户,如果有客户,也要选择客户的公司名称。
如果我使用此查询…
SELECT Orders.OrderId, Customers.CustomerId, Companies.Name FROM Orders LEFT OUTER JOIN Customers ON Orders.CustomerId = Customers.CustomerId INNER JOIN Companies OM Customers.CompanyId = Companies.CompanyId
…它只会返回有客户的订单。如果我替换INNER JOIN为LEFT OUTER JOIN…
INNER JOIN
LEFT OUTER JOIN
SELECT Orders.OrderId, Customers.CustomerId, Companies.Name FROM Orders LEFT OUTER JOIN Customers ON Orders.CustomerId = Customers.CustomerId LEFT OUTER JOIN Companies OM Customers.CompanyId = Companies.CompanyId
......它的工作原理,但我不明白为什么,因为之间的关系,这是必要的Customers,并Companies要求:客户 必须 有一个公司。
Customers
Companies
一种可行的替代方法似乎是:
SELECT Orders.OrderId, Customers.CustomerId, Companies.Name FROM Companies INNER JOIN Customers ON Companies.CompanyId = Customers.CompanyId RIGHT OUTER JOIN Orders OM Customers.CustomerId Orders.CustomerId
该查询具有我期望的内部和外部联接的数量,但问题是对我来说很难阅读,因为我将查询作为 订单 的查询记入其中,订单是选择的“根”,而不是选择的“根”公司。另外RIGHT OUTER JOIN,我的用法也不是很熟悉。
RIGHT OUTER JOIN
最后一个查询是设计器为SQL Server Reporting Services报表生成的查询的一小部分。我正在尝试在没有设计人员界面的情况下手动编写查询,因为它非常拥挤,并且在进行许多更改并且将来还会有更多更改之后,我在维护查询方面遇到了问题。因此,我想以某种方式为查询提供可读的结构。
问题:
语义上,联接按在from子句中出现的顺序进行处理。(由于SQL优化,它们可能实际上未按此顺序执行,但是该顺序对于定义结果集很重要。)
from
因此,当您这样做时:
from orders left outer join customers inner join companies
(on为此,我省去了那些会分散注意力的条款。)
on
SQL解释为:
from (orders left outer join customers) inner join companies
您正在执行inner join,因此值必须同时出现在两侧。在您的情况下,这会取消的效果left outer join。
inner join
left outer join
你要:
from orders left outer join (customers inner join companies)
这里有一些解决方案。
我的首选解决方案是left outer join用于所有联接。实际上,出于可读性和可维护性,我编写的几乎每个查询都将仅是查询表left outer join或[inner] join连接表。如果可以以一致的形式编写查询,则必须解析查询以了解联接的语义似乎是不必要的工作。
[inner] join
另一种解决方案是使用括号:
另一个解决方案是子查询:
from orders left outer join (select . . . from customers inner join companies) cc