2009-01-23 394 views
13

我有3个表,我不得不内部连接表A与表B,但表A和表C之间的左外SQL服务器 - 结合外部和内部连接

我可以结合外部和内部的加入同样的查询?我可以嵌套查询并获得所需的结果,但我无法在同一查询中同时执行两个连接。看起来在其他SQL语言中,加入的顺序很重要。这是SQL Server的情况吗?


好的,这是场景。

考虑3个表格。表A,表F,表D.

我将需要记录集包含D中的所有行,而不管它是否存在于F中(在它与A连接后)。所以,想到一个外部连接。我需要的是:

  1. 先做A和F之间的内连接来得到一组(这可能是一个空集)
  2. 然后做一个外连接,在与d(1)记录

回答

4

当然,你可以做同样的查询联接: -

FROM TableA a 
INNER JOIN Table b ON a.TableA_ID = b.TableA_ID 
LEFT OUTER JOIN Table c ON a.TableA_ID = c.TableA_ID 
+0

这并没有给出表D上的所有行(即你称之为c) – Paparazzi 2018-03-09 15:09:25

0

是的,你都可以做的是相同的查询,是的顺序是非常重要的。

13

如果我理解正确的话,你想是这样的:

select 
    * 
from 
    a 
    left outer join c 
     inner join b on c.bID = b.ID 
    on a.cID = c.ID 
+3

棘手!如果您将“on.cID = c.ID”移动到“left outer join c”的下方,这不会产生相同的结果,或者我只是错过了某些东西?这种行为是否记录在某处?我没有意识到这一点并不需要直接关注连接。 – Brandon 2015-08-18 02:29:12

+0

我认为你有一个和一个倒退 – Paparazzi 2018-03-09 15:10:30

1

从你的跟进,这听起来像你想有一个“有条件”内连接。

基本上,“如果A和B有记录,INNER JOIN to C”。

但是,您可能会遇到问题,其中查询中的INNER JOIN未显示记录,其中A没有与B或C关联的记录。如果它们位于相同的“范围”中,INNERS将始终运行,你不能有条件地让他们根据他们的顺序运行。

您必须使用两个LEFT连接并筛选出您不需要的记录,或者使用视图来限制INNER JOIN。

Ex。 左加入vw_MyView ON A.ID = vw_MyView.A_ID

其中MyView的表B和C与您的INNER JOIN。这将允许INNER JOIN在视图内部运行,然后您可以LEFT JOIN结果。

2

该订单应该不是的问题。

Venn Diagram

下面是来自于维基共享维恩图。无论查询顺序如何,您将获得圆A和B之间的重叠,其中C不包含A和B的组合的C列的空值。

0

问题可能并不是特定的连接(Anthony向你展示了如何处理你向我们描述的内容)。记住人们在使用左连接时经常会遇到问题,因为他们试图在where子句中引用连接右侧的表,从而将它从外连接转换为到内部联接(除非您正在查找第二个表字段为空的记录,这会为第一个表中的记录提供记录,而不是第二个表中的记录)。

如果我们说出您使用的实际代码并非产生期望的结果以及一些样本数据和样本结果,我们可以帮助您更好。

7

对于我来说,我需要把表的别名为我的查询才能正常工作:

SELECT * FROM ("purchased_items" p1 
    INNER JOIN "purchase_orders" po1 ON (po1."id" = p1."purchase_order_id")) AS p4 
LEFT OUTER JOIN (purchased_items p2 
     INNER JOIN "purchase_orders" po2 ON (po2."id" = p2."purchase_order_id")) AS p5 
ON (p4.item_variant_id = p5.item_variant_id AND p4.delivery_date < p5.delivery_date) 
WHERE p5.delivery_date IS NULL AND p4.delivered <> 0 
0

这在1至零或多个出现,其中许多具有FK。

两种方法
秩序on
outer参加最后

不幸你改变表名。我会用后面的名字。

declare @TableD TABLE (PeopleID int primary key, Name varchar(10)); 
INSERT INTO @TableD VALUES 
     (1, 'Chris') 
    , (2, 'Cliff') 
    , (3, 'Heather'); 

declare @TableA TABLE (ThingID int primary key, ThingName varchar(10)) 
INSERT INTO @TableA VALUES 
     (14, 'Bike') 
    , (17, 'Trailer') 
    , (18, 'Boat'); 

declare @TableF TABLE (PeopleID int, ThingID int, primary key (PeopleID, ThingID)); 
INSERT INTO @TableF VALUES 
     (1, 18) 
    , (1, 17) 
    , (2, 14); 

SELECT D.Name, A.ThingName 
FROM @TableD D 
LEFT JOIN @TableF F 
    JOIN @TableA A 
     ON A.ThingID = F.ThingID 
    ON F.PeopleID = D.PeopleID 
order by D.Name, A.ThingName; 

SELECT D.Name, A.ThingName 
FROM @TableF F 
JOIN @TableA A 
    ON A.ThingID = F.ThingID 
right join @TableD D 
    ON D.PeopleID = F.PeopleID 
order by D.Name, A.ThingName; 

Name  ThingName 
---------- ---------- 
Chris  Boat 
Chris  Trailer 
Cliff  Bike 
Heather NULL