2009-08-18 8 views
1

Ich habe die folgenden Tabellen (Ich habe die Daten in den Tabellen vereinfacht).Outer Join oder dynamische Abfrage, was ist der beste Weg zu gehen?

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 

Die RateExtra enthält nur 3 Werte mit Schlüssel des 1, 2 & 3 und Benzinzuschlag Namen, Verwaltungsgebühr und GST.

Dies funktioniert gut für den aktuellen Zweck. Eine Liste der Werte wird mit übereinstimmenden Datensätzen angezeigt, und RateExtra wird nur für den Namen rate_extra_name abgefragt.

So kann ich die folgenden Ergebnisse haben:

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

I'v Sie wurden aufgefordert, dies so zu ändern, dass jeder Datensatz, der jetzt zurückgegeben wird, Datensätze für jeden Wert in der RateExtra-Tabelle enthält. Wenn keine übereinstimmenden Datensätze vorhanden sind, sollten die Daten aus meiner RateTableExtra-Tabelle als NULL zurückgegeben werden. So sollte meine Daten kommen zurück wie:

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

I OUTER habe versucht, schließt sich aber sie scheinen nicht zu funktionieren, nehme ich an, weil die RateExtra-Daten mit der RateTableExtra verknüpft sind, die null zurückgeben würde. Ich überlege mir nun, eine dynamische Abfrage zu erstellen, die meine ursprüngliche Ergebnismenge erhält, iteriere sie nach rate_extra_id und fügt, falls sie nicht bereits in der Ergebnismenge enthalten ist, eine neue Zeile an die Ergebnisse an, wo ich NULL-Daten benötige. Ich gehe davon aus, dass das funktionieren würde, aber ich habe das Gefühl, dass es ein Mörder für die Leistung sein würde.

Gibt es einen besseren Weg, dies zu tun? Hoffe, dass jemand helfen kann, es würde wirklich geschätzt werden.

+0

Wenn Sie das RateTableExtra optional über einen rechten Join ausführen, müssen Sie das RateExtra optional auch über einen rechten Join vornehmen. Es ist nicht sinnvoll, den Grund für einen Aufpreis anzugeben, wenn tatsächlich kein Aufpreis vorhanden ist. Jacob – TheJacobTaylor

Antwort

1

Try this:

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 

Was Sie mit dieser Abfrage immer ist im Wesentlichen ein cartesianischen Join zwischen RateTable und RateExtra mit einem left join die Werte von RateTableExtra zu finden, die diese Paare entsprechen. Im Wesentlichen bringt diese Abfrage alle möglichen Kombinationen von RateTable und RateExtra zurück und zeigt Ihnen, welche Sie in Ihrer RateTableExtra Tabelle schnell haben.

Seien Sie vorsichtig mit kartesischen Joins. Sie können sehr schnell mit vernünftig großen Tischen außer Kontrolle geraten! Genießen Sie!

+0

Sie haben RateTableUsed vergessen, aber das ist in Ordnung, fügen Sie es einfach nach "von" ein (RateTableUsed rtu innerer Join RateTable rt on ...). Die "Reihenfolge von" hat keine Auswirkung - ändern Sie sie in "Reihenfolge von re.rate_extra_id". –

+1

@Todd: Ich hatte 'RateTableUsed ru' genannt, nicht 'rtu', also mein schlechtes. Was die "Ordnung nach" betrifft, hat es einen Effekt. Sonst ist 'rate_table_name' nicht mehr in Ordnung. Es sollte jedoch 'order by rt.rate_table_name, re.rate_extra_id' sein, also danke dafür! – Eric

+1

Es wäre klarer, den kartesischen Join mit CROSS JOIN ohne ON-Klausel statt INNER JOIN zu codieren. ON 1 = 1. –