SQL Developer中的左连接产生不完整的主/左表

时间:2017-11-22 15:31:03

标签: sql oracle join left-join

通常,当在两个表上执行左连接时,保留左表(A)的所有行,并且仅连接右表(B)以匹配连接条件,例如, A.ID = B.ID. 这适用于小型测试数据集。

然而,当我尝试使用相当大的集合B(即,B中唯一ID的数量是A中唯一ID的数量的约100倍)来连接集合A时,结果数据集仅包括那些A的那些行。与B匹配的ID,在我的理解中 - 是正常(内部)联接。

我通过左连接集合A获得了所需的结果表,只有那些具有匹配ID的集合B的那些行与集合A,但我不明白为什么简单的左连接不会产生相同的结果。

不幸的是,我无法用测试数据复制结果。

一般情况下,左连接后是否有可能导致左表被截断?

编辑:

设置A:

ID  name
X1  AB
X2  XY
X3  VT
X4  ZY
X5  YZ
X6  KJ
X7  HA
X8  BK
X9  LM

设置B:

ID  Var1
X1  blue
X11 red
X3  yellow
X4  blue
X12 yellow
X6  red
X7  orange
X7  blue
X8  green
X9  green
X10 blue

这给出了截断集A:

select A.*, B.Var1 from
setA A 
left join setB B
on A.ID = B.ID
where B.Var1 = 'blue';

这给了我想要的东西:

select A.*, B.Var1 from
setA A 
left join (select * from setB where Var1 = 'blue') B
on A.ID = B.ID;

我现在明白wherejoin过滤了加入结果,我需要将joinwhere视为两个独立的任务(正确吗?) 。 但是,对于我(作为非专家)来说,B.Var1 = 'blue'过滤联接结果虽然它显示B.Var1而不仅仅是Var1,但我可以理解更多很容易引用连接结果。 B.建议(对我来说)以某种方式影响连接中使用的左表。

2 个答案:

答案 0 :(得分:0)

TL / DR 使用setA A left join setB B on A.ID = B.ID and B.Var1 = 'blue'

  

保留左表(A)的所有行,并且仅连接右表(B)以匹配连接条件,例如, A.ID = B.ID"

目前尚不清楚你想说的是什么。

left join on被定义为返回inner join on行加上由null扩展的不匹配的左表行。如果结果中没有A的所有行,则您在where之后添加了inner join on(或right join onleft join on)。 每当您left join on时,请清楚记住您想要的inner join on相关内容;是什么决定了on

  

这是否意味着[outer] join中不允许使用where子句?

那个(评论)也很奇怪,因为where永远不会"在" a(外部或内部)连接,它总是在任何连接之后。 (您可以认为inner joincross joinon类似where,但优先级更高。)

  

这给了我想要的东西:

select A.*, B.Var1 from
setA A 
left join (select * from setB where Var1 = 'blue') B
on A.ID = B.ID;

这样做,"自然"措辞:

select A.*, B.Var1 from
setA A
left join setB B
on A.ID = B.ID
and B.Var1 = 'blue';
  

然而,对我来说(作为非专家)似乎并不自然

inner join on定义为返回符合(整个)cross join条件的on行。另一种描述这种情况的方法是,对于来自每个输入的每一行可能的一对组合行,但只有当它满足(整个)on条件时才输出。另一种描述这种情况的方法是,对于每个输入的每一对可能的行,只有当它们满足(整个)on条件时,它们才会组合成一个输出行。

有些人似乎使用后两种解释中的一种,但却有误解。他们认为inner join on输出不同而不是cross join,然后按on进行过滤。或者他们认为join只能是on两个输入中涉及(无论它们的意思是什么)列的条件 - 好像每个都必须被提及以便可以合并并且可能输出。但是没有 - on条件可以是任何东西,只是针对每个可能的输入行配对进行评估。

CROSS JOIN vs INNER JOIN:CROSS JOIN =(INNER)JOIN =逗号(",")
What is the difference between “INNER JOIN” and “OUTER JOIN”?
(要注意那里的许多其他答案中的废话和写作不好。)

  

其中B.Var1 = 'blue'会过滤联接结果,虽然它会显示B.Var1而不只是Var1,我可以更容易地理解它来引用联接结果。 B.建议(对我来说)以某种方式影响连接中使用的左表。

这个更加不清楚&奇怪的措辞。看起来你有误解,你需要放手。如果您试图强迫自己明确表达引用的语句,以及您希望joinon一起工作的方式,这可能会有所帮助。 (成为/成为专家的必要条件是不能容忍阅读,思考或写作的邋。。)

答案 1 :(得分:0)

您的查询在概念上技术上很好。你只是忘了(+)运算符。它应该是

select A.*, B.Var1 from
setA A 
left join setB B
on A.ID = B.ID
where B.Var1(+) = 'blue';  -- Notice the magic (+) symbol

(+)符号来自old style Oracle join syntax,可能会发音为“其中B.Var1,如果存在,则等于蓝色。”否则它只允许变量具有匹配值的行,这意味着它必须存在。

更现代的写作方式是:

select    A.*, 
          B.Var1 
from      setA A 
left join setB B  on  A.ID   = B.ID
                  AND B.Var1 = 'blue';  

换句话说,请将其从where中取出,并将其作为on条件的一部分,并将其保留为and