2009-08-18 12 views
1

J'ai les tableaux suivants (j'ai simplifié les données contenues dans les tableaux).Jointure externe ou requête dynamique, quelle est la meilleure solution?

RateTable 
- rate_table_id [int] 
- rate_table_name [nvarchar(50)] 

RateTableUsed 
- rate_used_id [int] 
- rate_table_id [int] (key to RateTable.rate_table_id) 
- customer_id [int] 

RateTableExtra 
- rate_table_extra_id [int] 
- rate_ extra_id [int] (key to RateExtra.rate_table_id) 
- rate_used_id [int] (key to RateTableUsed.rate_used_id) 

RateExtra 
- rate_ extra_id [int] 
- rate_extra_name [nvarchar(50)] 


select rate_table_name, rate_table_extra_id, rate_extra_name from RateTableUsed rtu 
    innerjoin RateTable rt on rtu.rate_table_id = rt.rate_table_id 
    innerjoin RateTableExtra rte on rte.rate_table_id = rt.rate_table_id 
    innerjoing RateExtr re on rte.rate_extra_id = re.rate_extra_id 

Le RateExtra ne contient que 3 valeurs avec de la touche 1, 2 & 3 et le supplément d'essence de noms, des frais de gestion et de la TPS.

Cela fonctionne très bien pour son but actuel. Une liste de valeurs est affichée avec les enregistrements correspondants et le RateExtra est interrogé uniquement pour le fichier rate_extra_name.

Je peut avoir les résultats suivants:

  • Ratetable1, 1, PetrolSurcharge
  • Ratetable1, 2, ManagementFee
  • Ratetable2, 3, PetrolSurcharge
  • Ratetable4, 4, TPS
  • Ratetable6, 5, PetrolSurcharge

Jev On nous a demandé de modifier cela afin que chaque enregistrement qui retourne maintenant inclut des enregistrements pour chaque valeur dans la table RateExtra. S'il n'y a aucun enregistrement correspondant alors les données de ma table RateTableExtra devraient revenir comme NULL. Donc, mes données devraient revenir comme:

  • Ratetable1, 1, PetrolSurcharge
  • Ratetable1, 2, ManagementFee
  • Ratetable1, NULL, TPS
  • Ratetable2, 3, PetrolSurcharge
  • Ratetable2, NULL, ManagementFee
  • Ratetable2, NULL, TPS
  • Ratetable4, NULL, PetrolSurcharge
  • Ratetable4, NULL, ManagementFee
  • Ratetable4, 4, TPS
  • Ratetable6, 5, PetrolSurcharge
  • Ratetable6, NULL, ManagementFee
  • Ratetable6, NULL, TPS

J'ai essayé les jointures OUTER mais ils ne semblent pas fonctionner je suppose parce que les données RateExtra sont liées au RateTableExtra qui renverrait null. J'envisage maintenant de créer une requête dynamique qui obtiendra mon ensemble de résultats d'origine, de parcourir pour vérifier rate_extra_id et, si ce n'est pas déjà dans le resultset, d'ajouter une nouvelle ligne aux résultats avec des données NULL là où j'en ai besoin. Je suppose que cela fonctionnerait, mais j'ai l'impression que ce serait un tueur sur la performance.

Y a-t-il une meilleure façon de faire cela? J'espère que quelqu'un peut aider, ce serait vraiment apprécié.

+0

Si vous rendez le RateTableExtra optionnel via une jointure de droite, vous devez également rendre le RateExtra optionnel via une jointure de droite. Cela n'a pas de sens d'inclure la raison d'un supplément quand il y a en fait, pas de frais supplémentaires. Jacob – TheJacobTaylor

Répondre

1

Essayez ceci:

select 
    rate_table_name, 
    rate_table_extra_id, 
    rate_extra 
from 
    RateTableUsed rtu 
    inner join RateTable rt on 
     rtu.rate_table_id = rt.rate_table_id 
    cross join RateExtra re 
    left outer join RateTableExtra rte on 
     rte.rate_table_id = rt.rate_table_id 
     and rte.rate_extra_id = re.rate_extra_id 
order by rt.rate_table_name, re.rate_extra_id 

Qu'est-ce que vous obtenez avec cette requête est, essentiellement, une jointure cartésienne entre RateTable et RateExtra, avec un left join pour trouver les valeurs de RateTableExtra qui correspondent à ces paires. Essentiellement, cette requête ramène tous les possibles combinaisons de RateTable et RateExtra, et vous montrant ceux que vous avez dans votre table RateTableExtra rapidement.

Faites attention aux assemblages cartésiens. Ils peuvent se dégrader très rapidement avec des tables de taille raisonnable! Profitez-en!

+0

Vous avez oublié RateTableUsed, mais ça va, mettez-le juste après "from" (RateTableUsed rtu inner join RateTable rt on ...). La "commande par" n'a aucun effet - remplacez-la par "order by re.rate_extra_id". –

+1

@Todd: J'avais appelé 'RateTableUsed ru', pas' rtu', donc mon mauvais. Quant à l'ordre par, il a un effet. Sinon, 'rate_table_name' sera détraqué. Cependant, il devrait être 'order by rt.rate_table_name, re.rate_extra_id', donc merci pour cela! – Eric

+1

Il serait plus clair de coder la jointure cartésienne avec CROSS JOIN sans clause ON, au lieu de INNER JOIN .. ON 1 = 1. –