我有三张桌子:
我想选择所有订单,无论他们是否有客户,如果他们有客户,那么也是客户的公司名称。
如果我使用此查询...
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
...
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
之间的关系是必需的:客户必须拥有公司。
另一种可行的方法似乎是:
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
的用法。
最后一个查询是设计器为SQL Server Reporting Services报告生成的查询的一小部分。我试图在没有设计器表面的情况下手动编写查询,因为它非常过度拥挤,并且在将来需要进行多次更改和更多更改之后,我遇到了维护查询的问题。所以,我想以某种方式给查询一个可读的结构。
问题:
答案 0 :(得分:12)
从语义上讲,连接按照它们在from
子句中出现的顺序进行处理。 (由于SQL优化,它们可能不会按此顺序实际执行,但排序对于定义结果集很重要。)
所以,当你这样做时:
from orders left outer join customers inner join companies
(我遗漏了on
条款,这些条款会为此目的分散注意力。)
SQL被解释为:
from (orders left outer join customers) inner join companies
您正在执行inner join
,因此值必须出现在两侧。在您的情况下,这会撤消left outer join
。
你想:
from orders left outer join (customers inner join companies)
以下是一些解决方案。
我首选的解决方案是对所有联接使用left outer join
。实际上,为了可读性和可维护性,我编写的几乎每个查询都只是left outer join
或[inner] join
连接表。如果你能以一致的形式编写查询,那么必须解析查询以理解连接的语义似乎是不必要的努力。
另一种解决方案是使用括号:
from orders left outer join (customers inner join companies)
另一个解决方案是子查询:
from orders left outer join (select . . . from customers inner join companies) cc
答案 1 :(得分:4)
INNER JOIN
,因此LEFT JOIN
实际上是INNER JOIN
。RIGHT JOIN
一般,因为它让一些开发人员感到困惑,因此不太可读。您通常可以通过有效使用LEFT JOIN
来以同样的方式编写查询。OUTER JOIN
后,后面的JOIN
也应为OUTER JOIN
。否则,您 MAY 会排除您不想要的行。答案 2 :(得分:3)
您可以像这样编写嵌套连接,以便对客户和公司的组合结果执行左连接,而不是对订单和客户的组合结果执行内连接。我基本上只是将内连接移动到左外连接的ON子句之前。其他人建议使用括号来获得此结果,如果内存服务,两种语法都将导致相同的执行。
SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
FROM Orders
LEFT OUTER JOIN Customers
INNER JOIN Companies
ON Customers.CompanyId = Companies.CompanyId
ON Orders.CustomerId = Customers.CustomerId
答案 3 :(得分:2)
查询1在公司有INNER JOIN,这意味着订单需要有vaild Customer(CompanyID) 如果你想使用INNER JOIN,它可以是这样的
SELECT Orders.OrderId, a.CustomerId, a.Name
FROM Orders
LEFT JOIN (
SELECT Customers.CustomerId, Companies.Name
FROM Customers
INNER JOIN Companies
OM Customers.CompanyId = Companies.CompanyId
) a
ON Orders.CustomerId = a.CustomerId
答案 4 :(得分:2)
1)它不起作用,因为当您INNER JOIN
到Companies
时,您需要在整个联接中存在,但由于Customer
不存在订单无法将Companies
记录关联回订单,因此不会返回。
2)我想如果你能获得没有相关公司的Customer
记录,你可以使用第二个查询,但如果这些表之间的关系是1比1,那就应该没问题。
3)第三个查询很好,但很难看。您加入公司和客户表,然后说不管结果集中有什么,我想要Orders
的所有内容。
4)我可能会加入子查询中的客户和公司,并将其重新加入订单。
查询:
SELECT Orders.OrderId,
Subquery.CustomerId,
Subquery.Name
FROM Orders
LEFT OUTER JOIN
(Select Customers.CustomerID,
Companies.Name
From Customers
INNER JOIN Companies
ON Customers.CompanyId = Companies.CompanyId) Subquery
On Orders.CustomerID = Subquery.CustomerID
5)谷歌搜索更容易回答这个问题。我确信可以在几分钟内写出更全面的信息。