Probleme mit INNER JOIN und LINKS / RECHTS OUTER JOIN

7

Ich habe drei Tabellen:

  • Bestellungen
    • Bestell-ID, int PK
    • CustomerId, int FK zum Kunden, NULL erlaubt


  • Kunden
    • CustomerId, int PK
    • CompanyId, int FK zu Company, NULL nicht erlaubt


  • Unternehmen
    • CompanyId, int PK
    • Name, nvarchar (50)

Ich möchte alle Bestellungen auswählen, egal ob sie einen Kunden haben oder nicht, und wenn sie einen Kunden haben, dann auch den Firmennamen des Kunden.

Wenn ich diese Abfrage verwende ...

%Vor%

... es gibt nur die Bestellungen zurück, die einen Kunden haben. Wenn ich INNER JOIN durch LEFT OUTER JOIN ...

ersetze %Vor%

... es funktioniert, aber ich verstehe nicht, warum dies notwendig ist, weil die Beziehung zwischen Customers und Companies benötigt wird: Ein Kunde muss eine Firma haben.

Ein alternativer Ansatz, der ebenfalls funktioniert, scheint zu sein:

%Vor%

Diese Abfrage hat die Anzahl der inneren und äußeren Joins, die ich erwarte, aber das Problem ist, dass es für mich schwer zu lesen ist, weil ich meine Abfrage als Abfrage von orders im Auge habe, wo eine Bestellung ist ist die "Wurzel" der Auswahl und nicht die Firma. Auch die Verwendung von RIGHT OUTER JOIN ist mir eher unbekannt.

Die letzte Abfrage ist ein kleiner Teil einer Abfrage, die vom Designer für SQL Server Reporting Services-Berichte generiert wurde. Ich versuche, die Abfrage manuell ohne die Designer-Oberfläche zu schreiben, da es sehr überfüllt ist und ich habe Probleme, die Abfrage nach vielen Änderungen zu verwalten, und in der Zukunft werden weitere Änderungen erwartet. Also möchte ich der Abfrage irgendwie eine lesbare Struktur geben.

Fragen:

  1. Warum funktioniert Abfrage 1 nicht wie erwartet?
  2. Ist Abfrage 2 die richtige Lösung obwohl (oder weil?) es zwei LINKE ANDERE VERBINDUNGEN verwendet?
  3. Ist Abfrage 3 die richtige Lösung?
  4. Gibt es eine bessere Möglichkeit, die Abfrage zu schreiben?
  5. Gibt es einige allgemeine Faustregeln und Vorgehensweisen, wie man eine Abfrage mit vielen äußeren und inneren Joins gut lesbar schreibt?
Slauma 08.05.2013, 14:08
quelle

5 Antworten

11

Semantisch werden Joins in der Reihenfolge verarbeitet, in der sie in der from -Klausel vorkommen. (Sie werden möglicherweise aufgrund von SQL-Optimierungen nicht in dieser Reihenfolge ausgeführt, aber die Reihenfolge ist wichtig für die Definition der Ergebnismenge.)

Also, wenn Sie das tun:

%Vor%

(Ich lasse die on -Klauseln weg, die eine Ablenkung für diesen Zweck darstellen.)

Die SQL wird interpretiert als:

%Vor%

Sie machen inner join , also müssen die Werte auf beiden Seiten erscheinen. In Ihrem Fall macht dies den Effekt von left outer join rückgängig.

Sie wollen:

%Vor%

Hier sind einige Lösungen.

Meine bevorzugte Lösung ist left outer join für alle Joins zu verwenden. Aus Gründen der Lesbarkeit und Wartbarkeit ist fast jede Abfrage, die ich schreibe, nur left outer join oder [inner] join , die die Tabellen verbindet. Wenn Sie die Abfragen in konsistenter Form schreiben können, scheint es unnötig zu sein, die Abfrage zu analysieren, um die Semantik der Verknüpfungen zu verstehen.

Eine andere Lösung ist die Verwendung von Klammern:

%Vor%

Eine andere Lösung ist eine Unterabfrage:

%Vor%     
Gordon Linoff 08.05.2013, 14:21
quelle
4
  1. Abfrage 1: Da% ce_de% auf Kunden steht, ist INNER JOIN effektiv ein LEFT JOIN .
  2. Abfrage 2 ist korrekt, da Sie alle Aufträge unabhängig von der Datenqualität / -bedingung sehen möchten.
  3. Ich möchte INNER JOIN s im Allgemeinen vermeiden, da es für einige Entwickler verwirrend ist und daher weniger lesbar ist. Sie können Ihre Abfrage im Allgemeinen so schreiben, dass sie dasselbe mit der effektiven Verwendung von RIGHT JOIN s tun.
  4. Abfrage 2 ist meine Empfehlung für so etwas Einfaches.
  5. Eine allgemeine Regel ... Sobald Sie LEFT JOIN in Ihre Abfrage eingefügt haben, sollten die folgenden OUTER JOIN s auch JOIN s sein. Andernfalls können Sie MAY Zeilen ausschließen, die Sie nicht beabsichtigt haben.
coge.soft 08.05.2013 14:28
quelle
3

Sie können Ihre Joins so verschachteln, dass der linke Join am kombinierten Ergebnis von Kunden und Unternehmen ausgeführt wird, anstatt dass ein interner Join am kombinierten Ergebnis von Aufträgen und Kunden ausgeführt wird. Ich habe im Grunde nur Ihren inneren Join vor die ON-Klausel für den linken äußeren Join verschoben. Jemand anders schlug Klammern vor, um dieses Ergebnis zu erhalten, beide Syntaxen führen zu derselben Ausführung, wenn der Speicher dient.

%Vor%     
David Söderlund 08.05.2013 14:34
quelle
2

Abfrage 1 hat INNER JOIN in der Firma, was bedeutet, dass eine Bestellung den Kunden (CompanyID) haben muss    Wenn Sie INNER JOIN verwenden möchten, kann es so sein

%Vor%     
EricZ 08.05.2013 14:22
quelle
2

1) Es funktioniert nicht, denn wenn Sie INNER JOIN bis Companies angeben, müssen Sie in der Gesamtheit der Verknüpfung bestehen, aber da Customer für die Reihenfolge nicht existiert, gibt es keine Möglichkeit zur Verknüpfung a Companies record zurück in die Reihenfolge und wird daher nicht zurückgegeben.

2) Ich nehme an, Sie könnten die zweite Abfrage verwenden, wenn Sie Customer Datensätze ohne zugehöriges Unternehmen erhalten, aber wenn die Relation zwischen diesen Tabellen 1 zu 1 ist, sollte es in Ordnung sein.

3) Die dritte Abfrage ist in Ordnung, aber hässlich. Sie treten den Firmen- und Kundentabellen bei und sagen dann, dass unabhängig von dem, was in dieser Ergebnismenge ist, ich alles von Orders will.

4) Ich würde wahrscheinlich Kunden und Firmen in einer Unterabfrage beitreten und mich dann den Bestellungen anschließen.

Abfrage:

%Vor%

5) Dies ist viel einfacher mit einer Google-Suche beantwortet. Ich bin sicher, es gibt umfassendere Informationen, die ich in ein paar Minuten schreiben könnte.

    
Eric J. Price 08.05.2013 14:29
quelle

Tags und Links