Dlaczego to Full Outer Join nie działa?


10

Wcześniej korzystałem z funkcji Full Outer Joins, aby uzyskać pożądane wyniki, ale być może nie do końca rozumiem tę koncepcję, ponieważ nie jestem w stanie osiągnąć czegoś, co powinno być prostym połączeniem.

Mam 2 tabele (które nazywam t1 i t2) z 2 polami:

t1

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

t2

Policy_Number   Loss
101              5
103              9
107              20

Usiłuję uzyskać sumę premii i sumę strat z obu tabel, a także numer polisy. Używam kodu:

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

Powyższy kod zwróci prawidłowe sumy całkowite, ale zgrupuje wszystkie rekordy, w których nie ma dopasowania numer_zasad w polu „NULL” numer_zasad.

Chciałbym, aby mój wynik wyglądał tak

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

itp.....

Nie chcę wyniku, który pokazuje NULL numer_zasad, jak pokazano poniżej (ponieważ nie ma czegoś takiego jak NULL numer_zasad. Jest to tylko suma, gdy numer_zasad z obu tabel nie pasuje):

Policy_Number    Prem_Sum   Loss_Sum
   NULL            35         NULL

Jeśli wybiorę i pogrupuję według t2.policy_number zamiast t1.policy_number, wówczas otrzymam coś takiego jak poniżej.

Policy_Number    Prem_Sum   Loss_Sum
   NULL            NULL         20

Ponownie, nie mam nic przeciwko zobaczeniu NULL w Prem_Sum lub w Loss_sum, ale nie chcę NULL w Policy_Number. Chciałbym, żeby moje wyniki były podobne

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

ect .....

Myślałem, że pełne połączenie zewnętrzne to umożliwi, ale chyba coś mi umknęło. Myślałem, że może mógłbym wybrać i pogrupować według zarówno t1.policy_number jak i t2.policy_number jako zapytanie podrzędne, a następnie może zrobić PRZYPADEK w zapytaniu zewnętrznym lub coś takiego? Nie sądzę, że powinno to być tak skomplikowane.

Wszelkie pomysły lub porady?

Odpowiedzi:


8

Powinieneś zrobić isnull na obu policjantach, abyś mógł poprawnie grupować.

Ponieważ jest to sprzężenie zewnętrzne, istnieje możliwość, że jedna strona sprzężenia ma wartość NULL, a jednocześnie nadal ma dane.

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)

... co oznacza, że ​​null są traktowane jak wartości SQL, dlatego potrzebujesz ISNULL (). Właśnie dlatego SQL jest tak źle określany. Jednak nadal używam go codziennie.
Paul-Sebastian Manole

4

Pełne sprzężenie zewnętrzne utworzy potrzebną strukturę rekordów, ale nie umieści dla Ciebie polisy numer 107 w Tabeli 1.

Myślę, że potrzebujesz czegoś takiego

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)

2

Aby podać trochę więcej informacji o tym, dlaczego określone zapytanie nie działa. Twój kod startowy to:

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 

Na pierwszy rzut oka wygląda na to, że powinno działać. Zauważ jednak, że podana trzecia kolumna to t1.policynumber. Jest to również jedyna kolumna grupująca. Z tego powodu SQL Server widzi tylko wartości w t1, pozostawiając wszystkie wartości nie w t1 jako null (ponieważ, pamiętaj, jest to pełne sprzężenie zewnętrzne). Kod isnull (t1.policynumber, t2.policynumber) dostarczy ci wszystkie wartości inne niż null w t1, a następnie użyjesz wartości w t2.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.