Почему это полное внешнее соединение не работает?


10

Я использовал Full Outer Joins прежде, чтобы получить желаемые результаты, но, возможно, я не до конца понимаю концепцию, потому что не могу выполнить то, что должно быть простым соединением.

У меня есть 2 таблицы (которые я назову t1 и t2) с 2 полями каждая:

t1

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

t2

Policy_Number   Loss
101              5
103              9
107              20

То, что я пытаюсь сделать, это получить сумму премии и суммы потерь из обеих таблиц, а также номер_политики. Код, который я использую:

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

Приведенный выше код вернет правильные итоговые суммы, но он сгруппирует все записи, в которых нет совпадения с policy_number в разделе "NULL" policy_number

Я хотел бы, чтобы мой результат выглядел так

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

и т.д.....

Я не хочу, чтобы результат, который показывает NULL policy_number, как показано ниже (поскольку не существует такой вещи, как NULL policy_number. Это всего лишь сумма, когда номер policy_number из обеих таблиц не совпадает):

Policy_Number    Prem_Sum   Loss_Sum
   NULL            35         NULL

Если я выбираю и группирую по t2.policy_number вместо t1.policy_number, то получаю что-то вроде ниже в качестве записи.

Policy_Number    Prem_Sum   Loss_Sum
   NULL            NULL         20

Опять же, я не против видеть NULL в Prem_Sum или в Loss_sum, но я не хочу NULL в Policy_Number. Я хотел бы, чтобы мои результаты были чем-то вроде

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

ЭСТ .....

Я думал, что полное внешнее соединение достигнет этого, но я думаю, что что-то упустил. Я думал, может быть, я мог бы выбрать и сгруппировать по t1.policy_number и t2.policy_number как подзапрос, а затем, возможно, сделать CASE во внешнем запросе или что-то в этом роде ??? Я не думаю, что это должно быть так сложно.

Есть идеи или советы?

Ответы:


8

Вы должны выполнить isnull для обоих номеров политик, чтобы вы могли правильно группировать.

Поскольку это внешнее соединение, существует вероятность того, что одна сторона соединения будет иметь значение NULL, при этом все еще сохраняя данные.

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)

... что означает, что значения NULL обрабатываются как значения в SQL, поэтому вам нужен ISNULL (). Вот почему SQL так плохо говорит. Все же я все еще использую это ежедневно.
Пол-Себастьян Маноле

4

Полное внешнее объединение создаст нужную вам структуру записи, но она не поместит политику номер 107 в таблицу 1 для вас.

Я думаю, что вам нужно что-то вроде

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

Чтобы предоставить немного больше информации о том, почему ваш конкретный запрос не работает. Ваш стартовый код был:

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 

На первый взгляд, похоже, это должно работать. Однако обратите внимание, что третий указанный столбец - t1.policynumber. Это также единственный столбец группировки. Из-за этого SQL Server видит только значения в t1, оставляя все значения, не входящие в t1, как нулевые (потому что, помните, это полное внешнее соединение). Код isnull (t1.policynumber, t2.policynumber) предоставит вам все ненулевые значения в t1, а затем использует значения в t2.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.