Olá,
Hoje o assunto é OUTER JOIN.
Essa dica de post eu peguei com o meu amigo Eduardo do blog bieduardo.blogspot.com/ .
Normalmente muitos profissionais caem nesta dúvida cruel.
Como fazer corretamente um OUTER JOIN?
Pirmeiro vamos relembrar o que é um OUTER JOIN.
"Um OUTER JOIN é um SIMPLE JOIN ou INNER JOIN  com uma "opção extendida " de trazer também os dados que não satisfazem a condição de JOIN.
No Oracle para usar LEFT ou RIGHT  OUTER JOIN em seu SQL você pode usar o caracter "+" entre parênteses para informar ao Oracle qual operador você está utilizando.Você também pode usar o padrão SQL92 para JOIN usando as palavras RIGHT OUTER JOIN e LEFT OUTER JOIN.
Mostrarei isso mais a frente no segundo post.
A explicação sobre de qual lado utilizar é simples:
Se a coluna que contém os dados nulos é a da direita você então coloca o sinal (+) na coluna da esquerda e vice-versa.
Ex. Nas tabelas A e B existe a  coluna ID do tipo NUMBER.
Na tabela A existe uma linha em que a coluna ID é nula,mas mesmo assim você precisa trazer esta linha na sua query ,neste caso você precisar fazer um JOIN para obtê - las.
ex.
select 
from tabela1 A,tabela2 B
where A.id = B.id(+) ;
No exemplo acima foi feito um LEFT JOIN pois quero retornar todos os dados da tabela A que não satisfazem a condição da JOIN .
Criando as tabelas de exemplo :
| dbajcc@DBPOST on 23-FEB-10 >create table jcc_join_a (seq number(2) ,  text varchar2(10)) ;  2    3 Table created. Elapsed: 00:00:00.03 dbajcc@DBPOST on 23-FEB-10 > insert into jcc_join_a  values(1,'disk1') ;  2 1 row created. Elapsed: 00:00:00.02 dbajcc@DBPOST on 23-FEB-10 > insert into jcc_join_a  values(2,'disk2') ;  2 1 row created. Elapsed: 00:00:00.00 dbajcc@DBPOST on 23-FEB-10 > insert into jcc_join_a(seq)  values(3) ;  2 1 row created. Elapsed: 00:00:00.00 dbajcc@DBPOST on 23-FEB-10 >commit ; Commit complete. Elapsed: 00:00:00.00 dbajcc@DBPOST on 23-FEB-10 > create table jcc_join_b (seq number(2) ,  text varchar2(10)) ;  2    3 Table created. Elapsed: 00:00:00.02 dbajcc@DBPOST on 23-FEB-10 > insert into jcc_join_b  values(1,'disk1') ;    2 1 row created. Elapsed: 00:00:00.01 dbajcc@DBPOST on 23-FEB-10 >  insert into jcc_join_b  values(2,'disk2') ;  2 1 row created. Elapsed: 00:00:00.00 dbajcc@DBPOST on 23-FEB-10 > insert into jcc_join_b(text)  values('disk3') ;  2 1 row created. Elapsed: 00:00:00.00 dbajcc@DBPOST on 23-FEB-10 > | 
Fazendo um RIGHT JOIN :
| dbajcc@DBPOST on 23-FEB-10 >select a.* ,b.*  from jcc_join_a a,       jcc_join_b b where a.seq(+) = b.seq ;  2    3    4        SEQ TEXT              SEQ TEXT ---------- ---------- ---------- ----------          1 disk1               1 disk1          2 disk2               2 disk2                                  disk3 Elapsed: 00:00:00.02 dbajcc@DBPOST on 23-FEB-10 > | 
Ou usando a sintaxe do padrão SQL92 :
| dbajcc@DBPOST on 24-FEB-10 >select  a.* ,b.*   2  from jcc_join_a a right outer join jcc_join_b b   3   on  a.seq = b.seq ;        SEQ TEXT              SEQ TEXT ---------- ---------- ---------- ----------          1 disk1               1 disk1          2 disk2               2 disk2                                  disk3 Elapsed: 00:00:00.00 dbajcc@DBPOST on 24-FEB-10 > | 
Acima destaquei em azul a coluna na qual é o alvo e que por sinal contém um campo SEQ nulo para o campo TEXT "disk3" .
Agora vamos fazer um LEFT JOIN :
| [oracle@marte ~]$ sqlplus dbajcc SQL*Plus: Release 11.2.0.1.0 Production on Wed Feb 24 07:49:02 2010 Copyright (c) 1982, 2009, Oracle.  All rights reserved. Enter password: Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production With the Partitioning, Automatic Storage Management, OLAP, Data Mining and Real Application Testing options dbajcc@DBPOST on 24-FEB-10 > select a.* ,b.*  from jcc_join_a a,       jcc_join_b b where a.seq = b.seq(+) ;  2    3    4        SEQ TEXT              SEQ TEXT ---------- ---------- ---------- ----------          1 disk1               1 disk1          2 disk2               2 disk2          3 Elapsed: 00:00:00.05 dbajcc@DBPOST on 24-FEB-10 > | 
Ou usando o outro tipo de sintaxe :
| dbajcc@DBPOST on 24-FEB-10 >select  a.* ,b.*   2  from jcc_join_a a left outer join jcc_join_b b   3  on  a.seq = b.seq ;        SEQ TEXT              SEQ TEXT ---------- ---------- ---------- ----------          1 disk1               1 disk1          2 disk2               2 disk2          3 Elapsed: 00:00:00.19 dbajcc@DBPOST on 24-FEB-10 > | 
Temos uma outra opção que é usar a um FULL OUTER JOIN para trazer os dados que não satisfazem a condição de JOIN das duas tabelas envolvidas.
| dbajcc@DBPOST on 24-FEB-10 >select  a.* ,b.*   2  from jcc_join_a a full outer join jcc_join_b b   3   on  a.seq = b.seq ;        SEQ TEXT              SEQ TEXT ---------- ---------- ---------- ----------          1 disk1               1 disk1          2 disk2               2 disk2                                  disk3          3 Elapsed: 00:00:00.01 dbajcc@DBPOST on 24-FEB-10 > | 
Nem vou trazer exemplos sobre Cartesian Join pois acredito ser de pouca utilidade.
Até,
Júlio César Corrêa 
 
 
 

2 comments:
Olá Júlio,
Excelente post. Aliás, seu blog está ótimo!
Abraços,
Eduardo Legatti
Olá Eduardo,
Muito obrigado por passar por aqui!
Vamos aprendendo dia após dia.
Ainda tenho muito que apreder a postar artigos com vocês mestres!
Post a Comment