DB2 Join - Inner Joins and Outer Joins



Desenvolvido por DORNELLES Carlos Alberto - Analista de Sistemas - Brasília DF. - cad_cobol@hotmail.com

DB2 Join - Inner Joins and Outer Joins

DB2 Join: Uma junção interna encontra e retorna dados correspondentes de tabelas, enquanto uma junção externa encontra e retorna dados correspondentes e alguns dados diferentes de tabelas.
Para combinar dois conjuntos de colunas com / sem remover duplicatas, consulte o uso de UNION vs UNION ALL em consultas SQL.
Para retornar o primeiro valor não nulo em uma lista de expressões de entrada, use a função COALESCE em consultas de junção.

An inner join finds and returns matching data from tables, while an outer join finds and returns matching data and some dissimilar data from tables.
For combining two sets of columns with/without removing duplicates refer UNION vs UNION ALL use in SQL Queries.
For returning the first non-null value in a list of input expressions use COALESCE function in Join Queries.

Inner join

Combina cada linha da tabela à esquerda com cada linha da tabela à direita, mantendo apenas as linhas nas quais a condição de junção é verdadeira.
Combines each row of the left table with each row of the right table, keeping only the rows in which the join condition is true.

Outer join

Inclui as linhas que são produzidas pela junção interna, mais as linhas ausentes, dependendo do tipo de junção externa:
Includes the rows that are produced by the inner join, plus the missing rows, depending on the type of outer join:

Left outer join

Inclui as linhas da tabela esquerda que estavam faltando na junção interna.
Includes the rows from the left table that were missing from the inner join.

Right outer join

Inclui as linhas da tabela certa que estavam faltando na junção interna.
Includes the rows from the right table that were missing from the inner join.

Full outer join

Inclui as linhas de ambas as tabelas que estavam faltando na junção interna.
Includes the rows from both tables that were missing from the inner join.


Produto cartesiano - Cartesian product

Quando duas ou mais tabelas são referenciadas na cláusula FROM de uma consulta, o servidor de banco de dados une as tabelas.
Se nem a cláusula FROM nem a cláusula WHERE especificam um predicado para a junção, o servidor calcula um produto cartesiano que contém m * n linhas, onde m é o número de linhas na primeira tabela e n é o número de linhas na segunda tabela.
Este produto é o conjunto de todas as combinações possíveis formadas pela concatenação de uma linha da primeira tabela com uma linha da segunda tabela.

When two or more tables are referenced in the FROM clause of a query, the database server joins the tables.
If neither the FROM clause nor the WHERE clause specifies a predicate for the join, the server computes a Cartesian product that contains m * n rows, where m is the number of rows in the first table and n is the number of rows in the second table.
This product is the set of all possible combinations formed by concatenating a row from the first table with a row from the second table.

  Table-(T1)            Table-(T2) 
ID NAME ID TITLE 10 Sandy 20 Sales Mgr 20 Sam 30 Clerk 30 Cindy 30 Manager 40 Sales Rep 50 Manager
Exemplo de junção padrão - Example of Standard Join 
SELECT * Resultado FROM T1, T2 ID NAME ID TITLE WHERE T1.ID = T2.ID 20 Sam 20 Sales Mgr ORDER BY T1.ID 30 Cindy 30 Clerk , T2.TITLE; 30 Cindy 30 Manager Exemplo de junção interna - Example of Inner Join
SELECT * Resultado FROM T1 ID NAME ID TITLE INNER JOIN T2 20 Sam 20 Sales Mgr ON T1.ID = T2.ID 30 Cindy 30 Clerk ORDER BY T1.ID 30 Cindy 30 Manager , T2.TITLE;

Uso ON e WHERE - ON and WHERE Usage

Apenas em uma junção interna, uma verificação ON e uma verificação WHERE funcionam da mesma maneira.
Ambos definem a natureza da junção e, como em uma junção interna, apenas as linhas correspondentes são retornadas, ambos atuam para excluir todas as linhas que não correspondem à junção.

In an inner join only, an ON and a WHERE check work much the same way.
Both define the nature of the join, and because in an inner join, only matching rows are returned, both act to exclude all rows that do not match the join.


Junção interna, usando verificação ON - Inner join, using ON check

Abaixo está uma junção interna que usa uma verificação ON para excluir “Manager”:
Below is an inner join that uses an ON check to exclude “Manager”:

Junção interna, usando verificação ON - Inner join, using ON check

 Abaixo está uma junção interna que usa uma verificação ON para excluir “Manager”:
 Below is an inner join that uses an ON check to exclude “Manager”:
SELECT * Resultado FROM T1 ID NAME ID TITLE INNER JOIN T2 20 Sam 20 Sales Mgr ON T1.ID = T2.ID 30 Cindy 30 Clerk AND T2.TITLE <> ’Manager’ ORDER BY T1.ID , T2.TITLE; Junção interna, usando a verificação WHERE - Inner join, using WHERE check
Aqui está a mesma consulta escrita usando uma cláusula WHERE Here is the same query written using a WHERE clause SELECT * Resultado FROM T1 ID NAME ID TITLE INNER JOIN T2 20 Sam 20 Sales Mgr ON T1.ID = T2.ID 30 Cindy 30 Clerk WHERE T2.TITLE <> ’Manager’ ORDER BY T1.ID , T2.TITLE;

União Externa Esquerda - Left Outer Join

Uma junção externa esquerda é o mesmo que dizer que quero todas as linhas da primeira tabela listadas, mais todas as linhas correspondentes na segunda tabela:
A left outer join is the same as saying that I want all of the rows in the first table listed, plus any matching rows in the second table:

Table-(T1)       Table-(T2)                  Resultado
 ID    NAM         ID    TITLE           ID   NAME       ID     TITLE     
 10    Sandy       20    Sales Mgr       10   Sandy      --     --------- 
 20    Sam         30    Clerk           20   Sam        20     Sales Mgr   
 30    Cindy       30    Manager         30   Cindy      30     Clerk
                   40    Sales Rep       30   Cindy      30     Manager
                   50    Manager
Exemplo de junção externa esquerda - Example of Left Outer Join
 SELECT *                                      
 FROM T1
 LEFT OUTER JOIN T2
 ON T1.ID = T2.ID
 ORDER BY T1.ID
        , T2.TITLE;

Uso ON e WHERE - ON and WHERE Usage

Em uma junção externa parcial (ou seja, à esquerda ou à direita), uma verificação ON funciona de maneira diferente, dependendo da tabela (campo) a que se refere:

  • Se se referir a um campo da tabela ao qual está sendo associada, ela determinará se a linha relacionada corresponde à associação ou não.
  • Se se referir a um campo na tabela a partir da qual está sendo associado, ele determinará se a linha relacionada encontra uma correspondência ou não.
    Independentemente disso, a linha será retornada.
No próximo exemplo, as linhas da tabela sendo unidas (ou seja, a visualização T2) que correspondem ao ID e que não são para um gerente são unidas a:

In a partial outer join (i.e. left or right), an ON check works differently, depending on what table (field) it refers to:

  • If it refers to a field in the table being joined to, it determines whether the related row matches the join or not.
  • If it refers to a field in the table being joined from, it determines whether the related row finds a match or not.
    Regardless, the row will be returned.

In the next example, those rows in the table being joined to (i.e. the T2 view) that match on ID, and that are not for a manager are joined to:

ON verificar a tabela sendo juntada para - ON check on table being joined to
SELECT * Resultado FROM T1 ID NAME ID TITLE LEFT OUTER JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam 20 Sales Mgr AND T2.TITLE <> ’Manager’ 30 Cindy 30 Clerk ORDER BY T1.ID , T2.TITLE;

ONDE verifique a tabela sendo unida - WHERE check on table being joined to

Se reescrevermos a consulta acima usando uma verificação WHERE, perderemos uma linha (de saída) porque a verificação é aplicada depois que a junção é feita e um JOB nulo não corresponde:
If we rewrite the above query using a WHERE check we will lose a row (of output) because the check is applied after the join is done, and a null JOB does not match:

SELECT *                                  Resultado
 FROM T1                      ID    NAME    ID     TITLE                       
 LEFT OUTER JOIN T2           20    Sam     20     Sales Mgr           
 ON T1.ID = T2.ID             30    Cindy   30     Clerk
 WHERE T2.TITLE <> ’Manager’  
 ORDER BY T1.ID
        , T2.TITLE;

Poderíamos tornar WHERE equivalente a ON, se também checássemos os nulos:
We could make the WHERE equivalent to the ON, if we also checked for nulls:
SELECT * Resultado FROM T1 ID NAME ID TITLE LEFT OUTER JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam 20 Sales Mgr WHERE (T2.TITLE <> ’Manager’ 30 Cindy 30 Clerk OR T2.TITLE IS NULL) ORDER BY T1.ID , T2.TITLE;

No próximo exemplo, as linhas da tabela sendo unidas (ou seja, a visualização T1) que correspondem ao ID e têm um NOME> 'D' participando da união.
Observe, entretanto, que as linhas T1 que não participam da junção (ou seja, ID = 30) ainda são retornadas:

In the next example, those rows in the table being joined from (i.e. the T1 view) that match on ID and have a NAME > ’D’ participate in the join.
Note however that T1 rows that do not participate in the join (i.e. ID = 30) are still returned:

SELECT *                                  Resultado
 FROM T1                      ID    NAME      ID     TITLE                       
 LEFT OUTER JOIN T2           10    Sandy     --     ---------        
 ON T1.ID = T2.ID             20    Sam       20     Sales Mgr           
 AND T2.NAME > ‘D’            30    Cindy     --     ---------
 ORDER BY T1.ID
        , T2.TITLE;

Se reescrevermos a consulta acima usando uma verificação WHERE (em NAME), perderemos uma linha porque agora a verificação exclui linhas do conjunto de respostas, em vez de participar da junção:

If we rewrite the above query using a WHERE check (on NAME) we will lose a row because now the check excludes rows from the answer-set, rather than from participating in the join:

SELECT *                                  Resultado
 FROM T1                      ID    NAME      ID     TITLE                       
 LEFT OUTER JOIN T2           10    Sandy     --     ---------        
 ON T1.ID = T2.ID             20    Sam       20     Sales Mgr           
 WHERE T2.NAME > ‘D’          
 ORDER BY T1.ID
        , T2.TITLE;

Ao contrário do exemplo anterior, não há como alterar a verificação WHERE acima para torná-la logicamente equivalente à verificação ON anterior.
ON e WHERE são aplicados em momentos diferentes e para finalidades diferentes e, portanto, fazem coisas completamente diferentes.

Unlike in the previous example, there is no way to alter the above WHERE check to make it logically equivalent to the prior ON check.
The ON and the WHERE are applied at different times and for different purposes, and thus do completely different things.


Junção Externa Direita - Right Outer Join

Uma junção externa direita é o inverso de uma junção externa esquerda.
Obtemos todas as linhas da segunda tabela listada, mais todas as linhas correspondentes na primeira tabela:

A right outer join is the inverse of a left outer join.
One gets every row in the second table listed, plus any matching rows in the first table:

Table-(T1)       Table-(T2)                  Resultado
 ID     NAME        ID     TITLE         ID   NAME     ID     TITLE    
 10     Sandy       20     Sales Mgr     20   Sam      20     Sales Mgr 
 20     Sam         30     Clerk         30   Cindy    30     Clerk
 30     Cindy       30     Manager       30   Cindy    30     Manager
                    40     Sales Rep     --   -----    40     Sales Rep   
                    50     Manager       --   -----    50     Manager        
 
Exemplo de junção externa direita - Example of Right Outer Join
SELECT * Resultado FROM T1 ID NAME ID TITLE RIGHT OUTER JOIN T2 20 Sam 20 Sales Mgr ON T1.ID = T2.ID 30 Cindy 30 Clerk ORDER BY T1.ID 30 Cindy 30 Manager , T2.TITLE; -- ----- 40 Sales Rep -- ----- 50 Manager

Uso ON e WHERE - ON and WHERE Usage

As regras para uso ON e WHERE são as mesmas em uma junção externa direita e em uma externa esquerda, exceto que as tabelas relevantes são invertidas.
The rules for ON and WHERE usage are the same in a right outer join as they are for a left outer, except that the relevant tables are reversed.


Junção externa completa - Full Outer Joins

Uma junção externa completa ocorre quando todas as linhas correspondentes em duas tabelas são unidas e também é retornada uma cópia de cada linha não correspondente em ambas as tabelas.
A full outer join occurs when all of the matching rows in two tables are joined, and there is also returned one copy of each non-matching row in both tables.

   Table-(T1)       Table-(T2)                  Resultado
 ID    NAME          ID    TITLE         ID   NAME     ID     TITLE     
 10    Sandy         20    Sales Mgr     10   Sandy    --     ---------  
 20    Sam           30    Clerk         20   Sam      20     Sales Mgr  
 30    Cindy         30    Manager       30   Cindy    30     Clerk
                     40    Sales Rep     30   Cindy    30     Manager
                     50    Manager       --   -----    40     Sales Rep   
                                         --   -----    50     Manager  

Exemplo de junção externa completa - Example of Full Outer Join
SELECT * Resultado FROM T1 ID NAM E ID TITLE FULL OUTER JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam 20 Sales Mgr ORDER BY T1.ID 30 Cindy 30 Clerk , T2.ID 30 Cindy 30 Manager , T2.TITLE; -- ----- 40 Sales Rep -- ----- 50 Manager

Uso ON e WHERE - ON and WHERE Usage

Em uma junção externa completa, uma verificação ON é bem diferente de uma verificação WHERE, pois nunca resulta na exclusão de uma linha do conjunto de respostas.
Tudo o que ele faz é categorizar a linha de entrada como sendo correspondente ou não correspondente.
Por exemplo, na seguinte junção externa completa, a verificação ON junta essas linhas com valores de chave iguais:

In a full outer join, an ON check is quite unlike a WHERE check in that it never results in a row being excluded from the answer set.
All it does is categorize the input row as being either matching or non-matching.
For example, in the following full outer join, the ON check joins those rows with equal key values:

União externa completa, correspondência nas teclas - Full Outer Join, match on keys
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL OUTER JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam 20 Sales Mgr ORDER BY T1.ID 30 Cindy 30 Clerk , T2.ID 30 Cindy 30 Manager , T2.TITLE; -- ----- 40 Sales Rep -- ----- 50 Manager

União externa completa, combinar nas chaves > 20 - Full Outer Join, match on keys > 20

No próximo exemplo, consideramos que apenas os IDs que correspondem, e que também têm um valor maior que 20, são uma correspondência verdadeira:
In the next example, we have deemed that only those IDs that match, and that also have a value greater than 20, are a true match:  

SELECT *                                  Resultado
 FROM T1                      ID    NAME      ID     TITLE                       
 FULL OUTER JOIN T2           10    Sandy     --     ---------        
 ON T1.ID = T2.ID             20    Sam       --     ---------        
 AND T1.ID > 20               30    Cindy     30     Clerk
 ORDER BY T1.ID               30    Cindy     30     Manager
        , T2.ID               --    -----     20     Sales Mgr                 
        , T2.TITLE;           --    -----     40     Sales Rep      
                              --    -----     50     Manager    

Observe como na instrução acima adicionamos um predicado e obtemos mais linhas!
Isso ocorre porque em uma junção externa um predicado ON nunca remove linhas.
Ele simplesmente os categoriza como correspondentes ou não correspondentes.
Se eles combinarem, ele se junta a eles.
Se não o fizerem, passa por eles.
No próximo exemplo, nada corresponde.
Consequentemente, cada linha é retornada individualmente.
Esta consulta é logicamente semelhante a fazer UNION ALL nas duas visualizações:

Observe how in the above statement we added a predicate, and we got more rows!
This is because in an outer join an ON predicate never removes rows.
It simply categorizes them as being either matching or non-matching.
If they match, it joins them.
If they don’t, it passes them through.
In the next example, nothing matches.
Consequently, every row is returned individually.
This query is logically similar to doing a UNION ALL on the two views:

União externa completa, combinar as chaves (nenhuma correspondência de linhas) - Full Outer Join, match on keys (no rows match)
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL OUTER JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam -- --------- AND +1 > -1 30 Cindy -- --------- ORDER BY T1.ID -- ----- 20 Sales Mgr , T2.ID -- ----- 30 Clerk , T2.TITLE; -- ----- 30 Manager -- ----- 40 Sales Rep -- ----- 50 Manager

As verificações ON são parecidas com as verificações WHERE, pois têm dois propósitos.
Em uma tabela, eles são usados ??para categorizar as linhas como correspondentes ou não correspondentes.
Entre as tabelas, eles são usados ??para definir os campos que devem ser unidos.

No exemplo anterior, a primeira verificação ON definiu os campos a serem unidos, enquanto a segunda junção identificou os campos que correspondiam à junção.
Como nada correspondeu (devido ao segundo predicado), tudo caiu na categoria “junção externa”.
Isso significa que podemos remover a primeira verificação ON sem alterar o conjunto de respostas:

ON checks are somewhat like WHERE checks in that they have two purposes.
Within a table, they are used to categorize rows as being either matching or non-matching.
Between tables, they are used to define the fields that are to be joined on.

In the prior example, the first ON check defined the fields to join on, while the second join identified those fields that matched the join.
Because nothing matched (due to the second predicate), everything fell into the “outer join” category.
This means that we can remove the first ON check without altering the answer set:

Junção externa completa, não corresponde às chaves (nenhuma correspondência de linhas) - Full Outer Join, don’t match on keys (no rows match)
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL OUTER JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam -- --------- AND +1 > -1 30 Cindy -- --------- ORDER BY T1.ID -- ----- 20 Sales Mgr , T2.ID -- ----- 30 Clerk , T2.TITLE; -- ----- 30 Manager -- ----- 40 Sales Rep -- ----- 50 Manager

O que acontece se tudo corresponder e não identificarmos os campos de junção?
O resultado em um produto cartesiano:

What happens if everything matches and we don’t identify the join fields?
The result in a Cartesian Product:

Junção externa completa, não corresponde às chaves (todas as linhas correspondem) - Full Outer Join, don’t match on keys (all rows match)
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL OUTER JOIN T2 10 Sandy 20 Sales Mgr ON T1.ID = T2.ID 10 Sandy 30 Clerk AND +1 <> -1 10 Sandy 30 Manager ORDER BY T1.ID 10 Sandy 40 Sales Rep , T2.ID 10 Sandy 50 Manager , T2.TITLE; 20 Sam 20 Sales Mgr 20 Sam 30 Clerk 20 Sam 30 Manager 20 Sam 40 Sales Rep 20 Sam 50 Manager 30 Cindy 20 Sales Mgr 30 Cindy 30 Clerk 30 Cindy 30 Manager 30 Cindy 40 Sales Rep 30 Cindy 50 Manager

Em uma junção externa, os predicados WHERE se comportam como se tivessem sido escritos para uma junção interna.
Em particular, eles sempre fazem o seguinte:

  • Predicados WHERE que definem campos de junção impõem uma junção interna nesses campos.
  • Predicados WHERE em campos que não são de junção são aplicados após a junção, o que significa que quando eles são usados ??em campos não nulos, eles negam a junção externa.

Aqui está um exemplo de um predicado de junção WHERE transformando uma junção externa em uma junção interna:

In an outer join, WHERE predicates behave as if they were written for an inner join.
In particular, they always do the following:

  • WHERE predicates defining join fields enforce an inner join on those fields.
  • WHERE predicates on non-join fields are applied after the join, which means that when they are used on not-null fields, they negate the outer join.

Here is an example of a WHERE join predicate turning an outer join into an inner join:

Junção externa completa, transformada em uma união interna por WHERE - Full Outer Join, turned into an inner join by WHERE
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL JOIN T2 20 Sam 20 Sales Mgr ON T1.ID = T2.ID 30 Cindy 30 Clerk WHERE T1.ID = T2.ID 30 Cindy 30 Manager ORDER BY T1.ID , T2.ID , T2.TITLE;

Para ilustrar algumas das complicações que as verificações de WHERE podem causar, imagine que queremos fazer um FULL OUTER JOIN em nossas duas visualizações de teste (veja abaixo), limitando a resposta às linhas em que o campo “T1 ID” seja menor que 30.
Existem várias maneiras de expressar essa consulta, cada uma dando uma resposta diferente:

Em nosso primeiro exemplo, o predicado “T1.ID < 30” é aplicado após a junção, o que elimina efetivamente todas as linhas “T2” que não correspondem (porque seu valor “T1.ID” é nulo):

To illustrate some of the complications that WHERE checks can cause, imagine that we want to do a FULL OUTER JOIN on our two test views (see below), limiting the answer to those rows where the “T1 ID” field is less than 30.
There are several ways to express this query, each giving a different answer:   

In our first example, the “T1.ID < 30” predicate is applied after the join, which effectively eliminates all “T2” rows that don’t match (because their “T1.ID” value is null):

Junção externa T1.ID < 30, verificação aplicada em WHERE (após a junção) - Outer join T1.ID < 30, check applied in WHERE (after join)
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam 20 Sales Mgr WHERE T1.ID <30 ORDER BY T1.ID , T2.ID , T2.TITLE;

No próximo exemplo, a verificação “T1.ID < 30” é feita durante a junção externa, onde não elimina nenhuma linha, mas limita aquelas que correspondem nas duas visualizações:
In the next example the “T1.ID < 30” check is done during the outer join where it does not any eliminate rows, but rather limits those that match in the two views:

Junção externa T1.ID < 30, verificação aplicada em ON (durante a junção) - Outer join T1.ID < 30, check applied in ON (during join)
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam 20 Sales Mgr AND T1.ID < 30 30 Cindy -- --------- ORDER BY T1.ID -- ----- 30 Clerk , T2.ID -- ----- 30 Manager , T2.TITLE; -- ----- 40 Sales Rep -- ----- 50 Manager

Imagine que o que realmente queria era ter a marca “T1.ID < 30” para se aplicar apenas àquelas linhas da tabela “T1”.
Em seguida, é necessário aplicar a verificação antes da junção, o que requer o uso de uma expressão de tabela aninhada:

Imagine that what really wanted to have the “T1.ID < 30” check to only apply to those rows in the “T1” table.
Then one has to apply the check before the join, which requires the use of a nested-table expression:

Junção externa T1.ID < 30, verificação aplicada em WHERE (antes da junção) - Outer join T1.ID < 30, check applied in WHERE (before join)
SELECT * Resultado FROM (SELECT * ID NAME ID TITLE FROM T1 10 Sandy -- --------- WHERE ID < 30) AS T1 20 Sam 20 Sales Mgr FULL OUTER JOIN T2 -- ----- 30 Clerk ON T1.ID = T2.ID -- ----- 30 Manager ORDER BY T1.ID -- ----- 40 Sales Rep , T2.ID -- ----- 50 Manager , T2.TITLE;

Observe como na consulta acima ainda obtivemos uma linha de volta com um ID 30, mas ela veio da tabela “T2”.
Isso faz sentido, porque a condição WHERE foi aplicada antes de chegarmos a esta tabela.
Existem várias maneiras incorretas de responder à pergunta acima.
No primeiro exemplo, devemos manter todas as linhas T2 não correspondentes, permitindo a passagem de quaisquer valores T1.ID nulos:

Observe how in the above query we still got a row back with an ID of 30, but it came from the “T2” table.
This makes sense, because the WHERE condition had been applied before we got to this table.
There are several incorrect ways to answer the above question.
In the first example, we shall keep all non-matching T2 rows by allowing to pass any null T1.ID values:

União externa T1.ID <30, (dá uma resposta errada - ver texto) - Outer join T1.ID < 30, (gives wrong answer - see text) 
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL OUTER JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam 20 Sales Mgr WHERE T1.ID < 30 -- ----- 40 Sales Rep OR T1.ID IS NULL -- ----- 50 Manager ORDER BY T1.ID , T2.ID , T2.TITLE;

Existem dois problemas com a consulta acima: Primeiro, ela só é apropriada para ser usada quando o campo T1.ID é definido como não nulo, o que ocorre neste caso.
Em segundo lugar, perdemos a linha na tabela T2 onde o ID era igual a 30.
Podemos corrigir este último problema adicionando outra verificação, mas a resposta ainda está errada:

There are two problems with the above query: First, it is only appropriate to use when the T1.ID field is defined as not null, which it is in this case.
Second, we lost the row in the T2 table where the ID equaled 30.
We can fix this latter problem, by adding another check, but the answer is still wrong:   

União externa T1.ID < 30, (dá uma resposta errada - ver texto) - Outer join T1.ID < 30, (gives wrong answer - see text)
SELECT * Resultado FROM T1 ID NAME ID TITLE FULL OUTER JOIN T2 10 Sandy -- --------- ON T1.ID = T2.ID 20 Sam 20 Sales Mgr WHERE T1.ID < 30 30 Cindy 30 Clerk OR T1.ID = T2.ID 30 Cindy 30 Manager OR T1.ID IS NULL -- ----- 40 Sales Rep ORDER BY T1.ID -- ----- 50 Manager , T2.ID , T2.TITLE;

As duas últimas verificações na consulta acima garantem que todas as linhas T2 sejam retornadas.
Mas eles também têm o efeito de retornar o campo NOME da tabela T1 sempre que houver uma correspondência. Dadas as nossas intenções, isso não deveria acontecer.

RESUMO: As condições da consulta WHERE são aplicadas após a junção.
Quando usado em uma junção externa, isso significa que eles se aplicam a todas as linhas de todas as tabelas.
Na verdade, isso significa que quaisquer condições WHERE em uma junção externa completa irão, na maioria dos casos, transformá-la em uma forma de junção interna.

The last two checks in the above query ensure that every T2 row is returned.
But they also have the affect of returning the NAME field from the T1 table whenever there is a match. Given our intentions, this should not happen.

SUMMARY: Query WHERE conditions are applied after the join.
When used in an outer join, this means that they applied to all rows from all tables.
In effect, this means that any WHERE conditions in a full outer join will, in most cases, turn it into a form of inner join.



© Copyright Tech Agilist