Associação esquerda da Oracle e erros de cláusulas where

10
CREATE TABLE "ATABLE1"
  (
    "COLUMN1" VARCHAR2(20 BYTE),
    "COLUMN2" VARCHAR2(20 BYTE)
  );

CREATE TABLE "ATABLE2"
  (
    "COLUMN1" VARCHAR2(20 BYTE),
    "COLUMN2" VARCHAR2(20 BYTE)
  );

Insert into ATABLE1 (COLUMN1,COLUMN2) values ('A','1');
Insert into ATABLE1 (COLUMN1,COLUMN2) values ('B','2');

Insert into ATABLE2 (COLUMN1,COLUMN2) values ('A',null);
Insert into ATABLE2 (COLUMN1,COLUMN2) values ('A','1');
Insert into ATABLE2 (COLUMN1,COLUMN2) values ('A','2');

select ATABLE1.column1, count(ATABLE2.column1) 
    from ATABLE1 Left OUTER JOIN ATABLE2 on ATABLE1.column1 = atable2.column1
    GROUP BY ATABLE1.column1;

Result

COLUMN1              COUNT(ATABLE2.COLUMN1) 
-------------------- ---------------------- 
A                    3                      
B                    0    

Isso funciona conforme o esperado. O problema é que eu sempre quero que todas as linhas de ATABLE1 sejam mostradas e também aplico algumas restrições.

select ATABLE1.column1, count(ATABLE2.column1) 
    from ATABLE1 Left OUTER JOIN ATABLE2 on ATABLE1.column1 = atable2.column1
    where atable2.column2 = '1'
    GROUP BY ATABLE1.column1;


COLUMN1              COUNT(ATABLE2.COLUMN1) 
-------------------- ---------------------- 
A                    1                      

Por que nem todas as colunas de ATABLE1 são exibidas, mesmo com a junção esquerda? Como posso fazê-los aparecer?

Muito obrigado antecipadamente.

Rafa de Castro
fonte
+1, especialmente pelo esforço que você
dedicou
"Por que nem todas as colunas de ATABLE1 estão sendo mostradas mesmo com a junção esquerda?" - você quis dizer 'todas as linhas'?
Jack diz que tente topanswers.xyz 18/01/12
@JackDouglas sim, isso faria mais sentido.
Aaron

Respostas:

7

Quando você adiciona filtros WHERE à tabela opcional / externa, altera a consulta para uma INNER JOIN. Você precisa adicionar a condição à junção, tabela derivada ou CTE.

select ATABLE1.column1, count(ATABLE2.column1) 
    from ATABLE1 Left OUTER JOIN ATABLE2
         on ATABLE1.column1 = atable2.column1 AND atable2.column2 = '1'
    GROUP BY ATABLE1.column1;
gbn
fonte
3

Por que nem todas as colunas de ATABLE1 são exibidas, mesmo com a junção esquerda? Como posso fazê-los aparecer?

Isso ocorre porque você está dizendo à sua consulta para trazer apenas de volta ATABLE.column1. Se você atender às consultas do gbn ou de Jack, basta indicar ATABLE1. * (Ou nomeie especificamente cada uma delas) na sua cláusula SELECT:

select ATABLE1.*, count(ATABLE2.column1) 
from ATABLE1 Left OUTER JOIN ATABLE2
     on ATABLE1.column1 = atable2.column1 AND atable2.column2 = '1'
GROUP BY ATABLE1.column1;
Aaron
fonte
11
Interessante, espero que o OP não esteja confuso sobre como listar todas as colunas. Por outro lado, foi o que eles pediram. +1.
precisa saber é o seguinte
2

Uma alternativa para adicionar a condição à junção é testar nullno filtro:

select ATABLE1.column1, count(ATABLE2.column1) 
    from ATABLE1 Left OUTER JOIN ATABLE2 on ATABLE1.column1 = atable2.column1
    where atable2.column2 is null or atable2.column2 = '1'
    GROUP BY ATABLE1.column1;

Prefiro essa variante, mas você pode considerá-la menos legível:

select ATABLE1.column1, count(ATABLE2.column1) 
    from ATABLE1 Left OUTER JOIN ATABLE2 on ATABLE1.column1 = atable2.column1
    where decode(atable2.column2,'1',1,null,1,0)=1
    GROUP BY ATABLE1.column1;

O único motivo para fazer isso é se, por algum motivo, você não conseguir colocar a condição no filtro (o que às vezes ocorre em uma consulta mais complexa)

Jack diz que tenta topanswers.xyz
fonte