【发布时间】:2013-05-02 19:33:18
【问题描述】:
我有三张桌子:
-
订单
- OrderId,int PK
- CustomerId,int FK to Customer,允许为 NULL
-
客户
- CustomerId,int PK
- CompanyId,int FK to Company,NULL 不允许
-
公司
- CompanyId,int PK
- 名称,nvarchar(50)
我想选择所有订单,无论他们是否有客户,如果他们有客户,那么还有客户的公司名称。
如果我使用这个查询...
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
这个查询有我期望的内连接和外连接的数量,但问题是我很难阅读,因为我将我的查询作为 orders 的查询考虑到订单在哪里是选择的“根”而不是公司。 RIGHT OUTER JOIN 的用法我也比较陌生。
最后一个查询是设计器为 SQL Server Reporting Services 报表生成的查询的一小部分。我试图在没有设计器表面的情况下手动编写查询,因为它非常拥挤,并且在进行许多更改后维护查询时遇到问题,并且预计将来会有更多更改。所以,我想以某种方式给查询一个可读的结构。
问题:
- 为什么查询 1 没有按预期工作?
- 查询 2 是否是正确的解决方案,尽管(或因为?)它使用了两个 LEFT OTHER JOINS?
- 查询 3 是正确的解决方案吗?
- 有没有更好的方法来编写查询?
- 是否有一些通用的经验法则和实践如何以可读性好的方式编写具有大量外部和内部联接的查询?
【问题讨论】:
-
我不是说你错了,但订单怎么可能没有客户。订单肯定是产品和客户的结合
-
@DavidB:不是真正的模特。想想“匿名”订单,生产公司有内部订单要在没有客户参考的情况下生产库存......或类似的东西。
-
这里的一个解决方案是拥有一个可以匹配这些的“匿名”客户记录,而不是根本没有客户。您可能会发现这种方法对许多其他报告也有帮助。
标签: sql sql-server tsql join