Probleme mit INNER JOIN und LEFT/RIGHT OUTER JOIN
Ich habe drei Tabellen:
- Bestellungen
- OrderId, int PK
- CustomerId, int FK zu Kunden, NULL erlaubt
- Kunden
- CustomerId, int PK
- CompanyId, int FK zu Unternehmen, NULL ist nicht erlaubt
- Unternehmen
- CompanyId, int PK
- Name nvarchar(50)
Möchte ich wählen Sie alle Aufträge, egal ob Sie ein Kunde oder nicht, und wenn Sie Kunden haben dann auch die Kunden der Firma.
Wenn ich diese Abfrage verwenden...
SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
FROM Orders
LEFT OUTER JOIN Customers
ON Orders.CustomerId = Customers.CustomerId
INNER JOIN Companies
OM Customers.CompanyId = Companies.CompanyId
...es gibt nur die Aufträge eines Kunden. Wenn ich ersetzen INNER JOIN
durch LEFT OUTER JOIN
...
SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
FROM Orders
LEFT OUTER JOIN Customers
ON Orders.CustomerId = Customers.CustomerId
LEFT OUTER JOIN Companies
OM Customers.CompanyId = Companies.CompanyId
...es funktioniert, aber ich verstehe nicht, warum dies notwendig ist, weil die Beziehung zwischen Customers
und Companies
erforderlich ist: Ein Kunde muss ein Unternehmen haben.
Einen alternativen Ansatz, der funktioniert so gut zu sein scheint:
SELECT Orders.OrderId, Customers.CustomerId, Companies.Name
FROM Companies
INNER JOIN Customers
ON Companies.CompanyId = Customers.CompanyId
RIGHT OUTER JOIN Orders
OM Customers.CustomerId Orders.CustomerId
Dieser Abfrage die Anzahl der inneren und äußeren Verknüpfungen, die ich erwarte, aber das problem ist, dass es schwer zu Lesen für mich, weil ich meine Abfrage als Abfrage von Bestellungen im Hinterkopf, wo ein Auftrag ist "root" der Auswahl-und nicht das Unternehmen. Auch die Verwendung von RIGHT OUTER JOIN
ist eher ungewohnt für mich.
Die Letzte Abfrage ist ein kleiner Teil einer Abfrage generiert, die der designer für SQL Server Reporting Services-Berichte. Ich bin versucht, zu schreiben, die Abfrage manuell ohne designer-Oberfläche, da ist es sehr überfüllt und ich habe Probleme zu erhalten, die Abfrage nach vielen änderungen und weitere änderungen sind zu erwarten in der Zukunft. So möchte ich in der Abfrage eine lesbare Struktur irgendwie.
Fragen:
- Warum nicht Abfrage 1 Arbeit, wie ich erwartet?
- Ist die Abfrage 2 die richtige Lösung, obwohl (oder weil?) es verwendet zwei LINKS ANDEREN VERKNÜPFUNGEN?
- Ist die Abfrage 3 die richtige Lösung?
- Gibt es eine bessere Art und Weise zu schreiben, die Abfrage?
- Gibt es einige Allgemeine Faustregeln und Praktiken, wie Sie eine Abfrage schreiben, mit einer Menge von outer-und inner joins in einer gut lesbaren Art und Weise?
- Im nicht sagen, Sie sind falsch, aber wie kann eine Bestellung nicht über einen Kunden. Ein Auftrag ist eine Kombination aus einem Produkt und ein Kunde sicher
- Kein reales Vorbild. Man denke nur an die "anonymen" Aufträge, bei denen eine Produktion Firma hat interne Aufträge zur Fertigung auf Lager, ohne Kunden-Referenz ... oder so ähnlich.
- Eine Lösung ist hier eine "anonyme" Kunden-Datensatz können Sie match-up für diese, eher als nicht-Kunde auf alle. Sie werden wahrscheinlich feststellen, dieser Ansatz hilft mit vielen anderen berichten auch.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Semantisch, joins werden in der Reihenfolge verarbeitet, in der
from
- Klausel. (Sie werden möglicherweise nicht tatsächlich ausgeführt-in dieser Reihenfolge-durch SQL-Optimierungen, aber die Reihenfolge ist wichtig für die Festlegung der Ergebnismenge.)So, wenn Sie tun:
(Ich gehe aus der
on
Klauseln, die eine Ablenkung für diesen Zweck.)SQL ist wie folgt interpretiert:
Du machst ein
inner join
, so müssen die Werte erscheinen auf beiden Seiten. In deinem Fall, macht die Wirkung derleft outer join
.Du willst:
Hier sind einige Lösungen.
Meine bevorzugte Lösung ist die Verwendung
left outer join
für alle joins. In der Tat, für die Lesbarkeit und Wartbarkeit, fast jede Abfrage, die ich Schreibe, ist nurleft outer join
oder[inner] join
verbinden der Tabellen. Nachdem zu durchsuchen, die Abfrage zu verstehen, die Semantik des joins zu sein scheint eine unnötige Mühe, wenn Sie schreiben können Sie die Abfragen in einer konsistenten form.Andere Lösung ist die Verwendung von Klammern:
Andere Lösung mit einer Unterabfrage:
INNER JOIN
auf Kunden, dieLEFT JOIN
ist effektiv einINNER JOIN
.RIGHT JOIN
s im Allgemeinen so, wie es ist verwirrend für einige Entwickler und ist daher schlechter lesbar. Sie können in der Regel schreiben Sie Ihre Anfrage in einer Weise zu tun, die gleiche Sache mit dem effizienten Einsatz vonLEFT JOIN
s.OUTER JOIN
in Ihrer Abfrage, dieJOIN
s, die Folgen sollten auchOUTER JOIN
s. Sonst, Sie KANN ausschließen von Zeilen, die Sie nicht wollen.Schreiben Sie Ihre joins verschachtelte so aus, dass der left join ausgeführt wird, auf das Ergebnis aus der Kombination von Kunden und Unternehmen statt eines inner join durchgeführt wird, die auf das kombinierte Ergebnis von Bestellungen und Kunden. Ich im Grunde nur verschoben, Ihre innere Verknüpfung, bevor Sie die ON-Klausel für den left-outer-join. Jemand anderes schlug vor, Klammer um dieses Ergebnis, beide Schreibweisen werden in der gleichen Ausführung, wenn der Speicher dient.
Abfrage 1 "INNER JOIN" - Unternehmen , was bedeutet, dass eine Bestellung müssen ein Gültiger Kunde(CompanyID)
Wenn Sie möchten, verwenden Sie INNER JOIN, es kann wie diese
1) Es funktioniert nicht, weil wenn Sie
INNER JOIN
zuCompanies
Sie machen es erforderlich, gibt es in der Gesamtheit der join, aber daCustomer
besteht nicht für die Bestellung gibt es keine Möglichkeit der Zuordnung einerCompanies
Datensatz wieder in die Ordnung und so ist es nicht zurückgegeben.2) ich nehme an, Sie könnte verwenden Sie die zweite Abfrage, wenn Sie ok sind, immer
Customer
Datensätze mit nicht verbundenen Unternehmen, aber wenn die Beziehung, die zwischen diesen Tabellen ist 1 zu 1 sollte es in Ordnung sein.3) Die Dritte Abfrage ist in Ordnung, aber hässlich. Sie verbinden die Unternehmen und Kunden-Tabellen und dann sagen, dass unabhängig davon, was in dieser Ergebnismenge, ich möchte alles von
Orders
.4) würde ich wahrscheinlich beitreten, Kunden und Unternehmen in einer Unterabfrage, left join, dass wieder Aufträge.
Abfrage:
5) Dies ist viel leichter zu beantworten, die mit einer google-Suche. Ich bin sicher, es ist mehr umfassende Informationen, die ich schreiben könnte, in ein paar Minuten.