2012-03-26 6 views
1

J'ai passé en revue des questions similaires mais je n'ai pas trouvé de réponse à mon problème spécifique. Je travaille avec SQL Server 2008 (T-SQL dans SQL Server Management Studio) (mais beaucoup plus utilisé pour Oracle et Crystal Reports).T-SQL: mêmes champs utilisant plusieurs jointures

scénario simplifié:

Tableau Client

customerID (pk)... 

Tableau InsuranceCoverage

customerID (composite pk) 
line (composite pk) 
insCompanyID (fk) 
insPlanID (fk) 

Tableau

Insurance Company
insCompanyID 
insCompanyName 
insCompanyAddr 

Tableau InsurancePlan

insPlanID 
insPlanName 
insPlanClass 

je besoin d'un rapport qui renvoie essentiellement ce qui suit sur une ligne:

  1. Quelques colonnes de Customer
  2. Assurance 1 - colonnes de Insurance Company et AssurancesPlan tables où InsuranceCoverage.line = 1
  3. Assurances 2 - colonnes de tables et InsurancePlan où Insurance Company InsuranceCoverage.line = 2
  4. Assurance 3 - colonnes de tables et InsurancePlan où Insurance Company InsuranceCoverage.line = 3

Je me sens très stupide de ne pas être en mesure de comprendre ce en dehors. Un client peut avoir jusqu'à trois assurances. Ce serait facile d'écrire plusieurs requêtes, mais je dois le configurer pour qu'il puisse s'exécuter automatiquement 1 fois par mois. J'ai utilisé la même table plusieurs fois dans le même rapport en utilisant des alias sur les jointures avant, mais cela ne fonctionnera pas ici à cause des critères InsuranceCoverage.line, non? Une sous-requête dans la clause from est-elle la réponse?

Répondre

2

Quelque chose comme ça?

SELECT 
    c.CustomerID, 
    cov1.*, 
    cov2.*, 
    cov3.*, 
    insco1.insCompanyName as insCompanyName1, 
    insco2.insCompanyName as insCompanyName2, 
    insco3.insCompanyName as insCompanyName3, 
    etc... 
FROM 
    Customer c 
    LEFT OUTER JOIN InsuranceCoverage cov1 on cov1.CustomerID = c.CustomerID AND cov1.line = 1 
    LEFT OUTER JOIN InsuranceCoverage cov2 on cov2.CustomerID = c.CustomerID AND cov2.line = 2 
    LEFT OUTER JOIN InsuranceCoverage cov3 on cov3.CustomerID = c.CustomerID AND cov3.line = 3 
    JOIN InsuranceCompany insco1 on insco1.insCompanyID = cov1.insCompanyID 
    JOIN InsuranceCompany insco2 on insco2.insCompanyID = cov2.insCompanyID 
    JOIN InsuranceCompany insco3 on insco3.insCompanyID = cov3.insCompanyID 
    JOIN InsurancePlan inspl1 on inspl1.insPlanID = cov1.insPlanID 
    JOIN InsurancePlan inspl2 on inspl2.insPlanID = cov2.insPlanID 
    JOIN InsurancePlan inspl3 on inspl3.insPlanID = cov3.insPlanID 
+0

Je pense que c'est le meilleur au cas où certains clients n'ont pas de couverture d'assurance. – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

+0

Merci beaucoup les gars. Vos réponses ont non seulement répondu à cette question, mais m'ont aussi aidé à résoudre un autre problème. Ce site est génial. –

1

vous pouvez faire une union de 2, 3, 4 comme une table dérivée et rejoindre 1 avec cela, comme ...

select t1.a,t1.b,t1.c, t2.d, t2.e, t2.f from customer t1, 
(select fk, d as d, 0 as e, 0 as f from ic where line=1 
    union select fk, 0, e, 0 from ic where line=2 
    union select fk, 0, 0, f from ic where line=3) as t2 
where t1.pk = t2. fk 

quelque chose comme ça

edit: oh, droit, si ils ne peuvent avoir aucune assurance à changer alors une jointure gauche comme ...

select t1.a,t1.b,t1.c, t2.d, t2.e, t2.f from customer t1 left join 
(select fk, d as d, 0 as e, 0 as f from ic where line=1 
    union select fk, 0, e, 0 from ic where line=2 
    union select fk, 0, 0, f from ic where line=3) as t2 
on t1.pk = t2.fk 

... ou quelque chose comme ça :)

2

I s et quelques variables de table pour montrer que cette requête fonctionne. Vous devrez les remplacer par les vrais noms de table et de colonne. Je crois que quelque chose comme ça fonctionnerait pour vous:

DECLARE @Customer TABLE (CustomerId INT) 

DECLARE @InsuranceCoverage TABLE 
(
    CustomerId INT 
    , Line INT 
    , InsuranceCompanyId INT 
    , InsurancePlanId INT 
) 

DECLARE @InsuranceCompany TABLE 
(
    Id INT 
    , Name VARCHAR(100) 
    , Addr VARCHAR(100) 
) 

DECLARE @InsurancePlan TABLE 
(
    Id INT 
    , Name VARCHAR(100) 
    , Class VARCHAR(100) 
) 

SELECT 
    C.* -- Customer colums. 
    -- Insurance1 columns. 
    , ICmp1.* 
    , IP1.* 
    -- Insurance2 columns. 
    , ICmp2.* 
    , IP2.* 
    -- Insurance3 columns. 
    , ICmp3.* 
    , IP3.* 
    FROM 
    @Customer C 
    LEFT JOIN @InsuranceCoverage ICov1   
     INNER JOIN @InsuranceCompany ICmp1 
      ON ICmp1.Id = ICov1.InsuranceCompanyId 
     INNER JOIN @InsurancePlan IP1 
      ON IP1.Id = ICov1.InsurancePlanId 
     ON ICov1.CustomerId = C.CustomerId 
     AND ICov1.Line = 1 
    LEFT JOIN @InsuranceCoverage ICov2 
     INNER JOIN @InsuranceCompany ICmp2 
      ON ICmp2.Id = ICov2.InsuranceCompanyId 
     INNER JOIN @InsurancePlan IP2 
      ON IP2.Id = ICov2.InsurancePlanId 
     ON ICov2.CustomerId = C.CustomerId 
     AND ICov2.Line = 2 
    LEFT JOIN @InsuranceCoverage ICov3 
     INNER JOIN @InsuranceCompany ICmp3 
      ON ICmp3.Id = ICov3.InsuranceCompanyId 
     INNER JOIN @InsurancePlan IP3 
      ON IP3.Id = ICov3.InsurancePlanId 
     ON ICov3.CustomerId = C.CustomerId 
     AND ICov3.Line = 3 
+2

Que se passe-t-il si un client n'a qu'une seule couverture? –

+0

Basculer vers les jointures à gauche.:) –

+0

@Chris Shain: Ah, il a dit jusqu'à 3 assurances ..., je vais le modifier. Merci. –