Por que essa junção externa completa não está funcionando?

10

Eu usei Junções Externas Completas antes para obter os resultados desejados, mas talvez eu não entenda completamente o conceito porque não sou capaz de realizar o que deve ser uma junção simples.

Eu tenho 2 tabelas (que chamarei de t1 e t2) com 2 campos cada:

t1

Policy_Number Premium
101             15
102              7
103             10
108             25
111              3

t2

Policy_Number   Loss
101              5
103              9
107              20

O que estou tentando fazer é obter a soma do Premium e da soma das perdas das duas tabelas e também do Policy_Number. O código que estou usando é:

select sum(premium) Prem_Sum, sum(Loss) Loss_Sum, t1.policynumber
from t1 full outer join t2 on t1.policynumber = t2.policynumber
group by t1.policynumber

O código acima retornará os totais de soma corretos, mas agrupará todos os registros onde não houver uma correspondência de policy_number em "NULL" policy_number.

Gostaria que meu resultado fosse assim

Policy_Number    Prem_Sum    Loss_Sum
    107            NULL        20
    111              3        NULL
    101             15          5

etc .....

Eu não quero um resultado que mostre um número de política NULL como mostrado abaixo (já que não existe um número de política NULL. Esse é apenas o total para quando o número da política de ambas as tabelas não corresponder):

Policy_Number    Prem_Sum   Loss_Sum
   NULL            35         NULL

Se eu selecionar e agrupar por t2.policy_number em vez de t1.policy_number, recebo algo como abaixo como um registro.

Policy_Number    Prem_Sum   Loss_Sum
   NULL            NULL         20

Novamente, não me importo de ver NULL em Prem_Sum ou em Loss_sum, mas não quero um NULL em Policy_Number. Gostaria que meus resultados fossem algo como

Policy_Number    Prem_Sum    Loss_Sum
    107            NULL        20
    111              3        NULL
    101             15          5

ect .....

Eu pensei que a junção externa completa faria isso, mas acho que estou perdendo alguma coisa. Eu estava pensando que talvez eu pudesse selecionar e agrupar por t1.policy_number e t2.policy_number como uma subconsulta e, em seguida, talvez fazer um CASE na consulta externa ou algo assim ??? Eu não acho que deveria ser tão complicado.

Alguma idéia ou conselho?

Juan Velez
fonte

Respostas:

8

Você deve fazer um nulo nos dois números de políticas para poder agrupar corretamente.

Como é uma junção externa, existe a possibilidade de um lado da junção ser NULL enquanto ainda possui dados.

select sum(premium) Prem_Sum, sum(Loss) Loss_Sum, isnull(t1.policynumber, t2.policynumber)
from t1 full outer join t2 on t1.policynumber = t2.policynumber
group by isnull(t1.policynumber, t2.policynumber)
Derek Kromm
fonte
... o que significa que os nulos são tratados como valores pelo SQL e é por isso que você precisa de ISNULL (). É por isso que o SQL é tão ruim. Ainda o uso diariamente.
Paul-Sebastian Manole
4

A junção externa completa criará a estrutura de registro que você precisa, mas não colocará a política número 107 na Tabela 1 para você.

Eu acho que o que você precisa é algo na linha de

select coalesce(t1.policy_number, t2.policy_number) as PolicyNumber, 
sum(t1.premium) as PremSum, sum(t2.loss) as LossSum
from t1 full outer join t2 on t1.policy_number = t2.policy_number
group by coalesce(t1.policy_number, t2.policy_number)
Hellion
fonte
2

Para fornecer um pouco mais de informações sobre por que sua consulta específica não funcionou. Seu código inicial era:

select sum(premium) Prem_Sum, sum(Loss) Loss_Sum, t1.policynumber 
from t1 full outer join t2 on t1.policynumber = t2.policynumber 
group by t1.policynumber 

À primeira vista, parece que deve funcionar. No entanto, observe que a terceira coluna especificada é t1.policynumber. Essa também é a única coluna de agrupamento. Por causa disso, o SQL Server vê apenas os valores em t1, deixando os valores que não estão em t1 como nulos (porque, lembre-se, essa é uma junção externa completa). O código isnull (t1.policynumber, t2.policynumber) fornecerá todos os valores não nulos em t1 e, em seguida, use valores em t2.

DForck42
fonte