¿Por qué esta unión externa completa no funciona?

10

He usado Full Outer Joins antes para obtener los resultados deseados, pero tal vez no entiendo completamente el concepto porque no puedo lograr lo que debería ser una simple unión.

Tengo 2 tablas (que llamaré t1 y t2) con 2 campos cada una:

t1

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

t2

Policy_Number   Loss
101              5
103              9
107              20

Lo que intento hacer es obtener la suma de la prima y la suma de las pérdidas de ambas tablas y también el número de política. El código que estoy usando es:

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

El código anterior devolverá los totales de suma correctos, pero agrupará todos los registros donde no haya una coincidencia de número_política bajo el número_política "NULL".

Me gustaría que mi resultado se vea así

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

etc .....

No quiero un resultado que muestre un número de política NULL como se muestra a continuación (ya que no existe un número de política NULL. Esto es solo el total para cuando el número de política de ambas tablas no coincide):

Policy_Number    Prem_Sum   Loss_Sum
   NULL            35         NULL

Si selecciono y agrupo por t2.policy_number en lugar de t1.policy_number, obtengo algo como a continuación como registro.

Policy_Number    Prem_Sum   Loss_Sum
   NULL            NULL         20

Nuevamente, no me importa ver NULL en Prem_Sum o en Loss_sum, pero no quiero NULL en Policy_Number. Me gustaría que mis resultados fueran algo así

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

ect .....

Pensé que la combinación externa completa lograría esto, pero supongo que me falta algo. ¿Estaba pensando que tal vez podría seleccionar y agrupar por t1.policy_number y t2.policy_number como una subconsulta y luego quizás hacer un CASO en la consulta externa o algo así? No creo que deba ser tan complicado.

¿Alguna idea o consejo?

Juan velez
fuente

Respuestas:

8

Debe hacer un nulo en ambos números de póliza para poder agruparlo adecuadamente.

Como se trata de una unión externa, existe la posibilidad de que un lado de la unión sea NULO mientras aún tenga datos.

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
fuente
... lo que significa que los valores nulos son tratados como valores por SQL, razón por la cual necesita ISNULL (). Esta es la razón por la cual SQL es tan malo. Sin embargo, todavía lo uso a diario.
Paul-Sebastian Manole
4

La combinación externa completa creará la estructura de registros que necesita, pero no incluirá la política número 107 en la Tabla 1.

Creo que lo que necesitas es algo en la línea 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)
Gamberro
fuente
2

Para proporcionar un poco más de información sobre por qué su consulta específica no funcionó. Su código de inicio fue:

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 

A primera vista, parece que debería funcionar. Sin embargo, observe que la tercera columna especificada es t1.policynumber. Esta es también la única columna de agrupación. Debido a esto, SQL Server solo ve los valores en t1, dejando cualquier valor que no esté en t1 como nulo (porque, recuerde, esta es una combinación externa completa). El código isnull (t1.policynumber, t2.policynumber) le proporcionará todos los valores no nulos en t1, luego use los valores en t2.

DForck42
fuente