Pourquoi cette jointure externe complète ne fonctionne-t-elle pas?

10

J'ai déjà utilisé des jointures complètes pour obtenir les résultats souhaités, mais je ne comprends peut-être pas complètement le concept car je ne suis pas en mesure d'accomplir ce qui devrait être une simple jointure.

J'ai 2 tables (que j'appellerai t1 et t2) avec 2 champs chacune:

t1

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

t2

Policy_Number   Loss
101              5
103              9
107              20

Ce que j'essaie de faire est d'obtenir la somme de la prime et de la somme des pertes des deux tables et également du Policy_Number. Le code que j'utilise est:

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

Le code ci-dessus renverra les totaux corrects mais il regroupera tous les enregistrements où il n'y a pas de correspondance policy_number sous "NULL" policy_number.

J'aimerais que mon résultat ressemble à ceci

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

etc.....

Je ne veux pas d'un résultat qui montre un numéro de politique NULL comme indiqué ci-dessous (car il n'y a pas de numéro de politique NULL. C'est juste le total pour quand le numéro de politique des deux tables ne correspond pas):

Policy_Number    Prem_Sum   Loss_Sum
   NULL            35         NULL

Si je sélectionne et regroupe par t2.policy_number au lieu de t1.policy_number, j'obtiens quelque chose comme ci-dessous en tant qu'enregistrement.

Policy_Number    Prem_Sum   Loss_Sum
   NULL            NULL         20

Encore une fois, cela ne me dérange pas de voir NULL sous Prem_Sum ou sous Loss_sum mais je ne veux pas de NULL sous Policy_Number. J'aimerais que mes résultats soient quelque chose comme

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

ect .....

Je pensais que la jointure externe complète accomplirait cela, mais je suppose que je manque quelque chose. Je pensais que je pourrais peut-être sélectionner et regrouper à la fois t1.policy_number et t2.policy_number comme sous-requête, puis peut-être faire un CASE dans la requête externe ou quelque chose ??? Je ne pense pas que cela devrait être aussi compliqué.

Des idées ou des conseils?

Juan Velez
la source

Réponses:

8

Vous devez effectuer un isnull sur les deux numéros de police afin de pouvoir vous regrouper correctement.

Comme il s'agit d'une jointure externe, il est possible qu'un côté de la jointure soit NULL tout en ayant des données.

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
la source
... ce qui signifie que les valeurs nulles sont traitées comme des valeurs par SQL, c'est pourquoi vous avez besoin d'ISNULL (). C'est pourquoi SQL a si mauvaise gueule. Pourtant, je l'utilise toujours quotidiennement.
Paul-Sebastian Manole
4

La jointure externe complète créera la structure d'enregistrement dont vous avez besoin, mais elle ne mettra pas la stratégie 107 dans le tableau 1 pour vous.

Je pense que ce dont vous avez besoin est quelque chose du genre

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
la source
2

Pour fournir un peu plus d'informations sur les raisons pour lesquelles votre requête spécifique n'a pas fonctionné. Votre code de départ était:

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 

À première vue, cela semble fonctionner. Cependant, notez que la troisième colonne spécifiée est t1.policynumber. Il s'agit également de la seule colonne de regroupement. À cause de cela, SQL Server ne voit que les valeurs dans t1, laissant toutes les valeurs qui ne sont pas dans t1 comme nulles (car, rappelez-vous, il s'agit d'une jointure externe complète). Le code isnull (t1.policynumber, t2.policynumber) vous fournira toutes les valeurs non nulles en t1, puis utilisera les valeurs en t2.

DForck42
la source