2009-06-10 9 views
2

Ist es wahr, dass egal welche Art von Join Sie verwenden, wenn Ihre WHERE-Klausel die fk einer Tabelle pk = andere Tabelle überprüft, wird es gleich wie ein innerer Join, solange die Ergebnismenge übereinstimmt? Mit anderen Worten, wenn Ihre SQL-Abfrage einige Sachen wie hat:Stimmt es, dass alle Arten von Joins auf innere Joins reduziert werden, wenn die Tabelle pk = andere Tabellen fk überprüft?

"Wählen Sie ... von A Links Join B On (...) E, F Volle Äußere Join G auf (A.pk = G.fk) ... WHERE A.pk = G.fk und A.pk = B.fk und etc ... "

In der obigen Abfrage ist A linksbündig mit B, während G äußerlich mit A verbunden ist auf seinem fk. Da die where-Klausel jedoch die beiden Überprüfungen enthält, reduziert sich die gesamte Abfrage auf Folgendes:

"Wählen ... aus A INNER JOIN B Ein (...) E, F INNER Join G on (A.pk = G.fk) ... WO usw. ... " ? Der Grund für die Abfrage dieser Abfrage ist, dass ich viele kartesische Joins zusammen mit where-Klauseln, die auf einer Tabelle sind, haben, die die Abfrage verlangsamen. Ich habe daran gedacht, die kartesischen Produkte entweder durch Linke Joins zu ersetzen oder um alle Where-Klauseln oder alle Inner Joins zu behalten.

Antwort

1

Ja, wenn Sie refernce Die rechte Seite eines linken äußeren Joins in einer where-Klausel mit Ausnahme von "wo mein Feld null ist", Sie haben einen inneren Join erstellt. Dies liegt daran, dass alles herausgefiltert wird, das diese Bedingung nicht erfüllt, einschließlich aller Datensätze, die keine Übereinstimmung mit der ursprünglichen Tabelle aufweisen. Gleiches gilt für die anderen nicht-inneren Joins. Um es zu umgehen, legen Sie die Bedingung in den Join.Beispiel (dies macht es zu einem inneren Verknüpfung):

Select field1, field2 from mytable mt 
left join mytable2 mt2 on mt.id = m2.id 
where mt1.field1 = 'hello' and mt2.field2 = 'test' 

Rewritten die linken zu erhalten verbinden:

Select field1, field2 from mytable mt 
left join mytable2 mt2 on mt.id = m2.id and mt2.field2 = 'test' 
where mt1.field1 = 'hello' 

ich auch etwas kommentieren möchten Sie in einem Kommentar sagten aber dachte, meine Antwort wäre zu lange für einen weiteren Kommentar.

"Wählen Sie ... Von einem inneren Join B auf (A.id = B.a_id), C, D, F wo A.id = F.id" zu: "Wählen Sie ... Von A Inner Verknüpfen Sie B auf (A.id = B.a_id), C, D INNER JOIN F auf A.id = F.a_id "

Sie möchten solche Syntaxen nicht kombinieren; Das wird sehr schwer zu pflegen. Tatsächlich empfehle ich, niemals die Kommasyntax im alten Stil zu verwenden, da sie zufälligen Kreuzverbindungen unterliegt. Also in Ihrem Beispiel würde ich schreiben das Ergebnis erhalten setzen Sie derzeit bekommen (zumindest jemand Aufrechterhaltung wissen Sie indended ein Cross Join statt tat es durch Zufall):

Select ... From A 
INNER JOIN B on A.id = B.a_id 
INNER JOIN F on A.id = F.a_id 
CROSS JOIN C 
CROSS JOIN D 

Altenatively wenn die Cross-Join ist zufällig, würde der Code ändern:

Select ... From A 
INNER JOIN B on A.id = B.a_id 
INNER JOIN F on A.id = F.a_id 
INNER JOIN C on (fill in the join fields) 
INNER JOIN D on (fill in the join fields) 
3

Ja, das ist ein Umweg, um eine innere Verbindung zu bekommen.

Denken Sie darüber nach, wie das funktioniert: Es zieht alles von A, dann die passenden B oder Nullen, dann alle G (Nullen auf den A/B- und G-Seiten) und filtert dann im Wesentlichen alles heraus, was eine Nullseite hat dazu (die WHERE-Klausel). Also, ja, der INNER JOIN ist wahrscheinlich schneller.

Eine gemeinsame Quelle dieser Verwirrung ist, dass dies:

SELECT * FROM a INNER JOIN b ON a.id = b.id WHERE b.something = 'awesome' 

jedoch derselbe transitiv Ansatz nicht mit voller/Außen Arbeit verbindet, wie es:

SELECT * FROM a INNER JOIN b ON a.id = b.id AND b.something = 'awesome' 

äquivalent ist macht den Join und filtert dann (abhängig von den Filtern, natürlich, und dem Optimierer).

Kurz gesagt: Verwenden Sie innere Joins, wenn Sie wirklich einen inneren Join wollen.

Edit: Ich sollte auch beachten, dass es nicht der PK/FK-Deal ist, ist es, wenn Sie im Wesentlichen Ihre ON-Klausel in der WHERE-Klausel wiederholen, dass die vollen/äußeren Joins äquivalent zu inneren Joins werden.

+0

auch etw wie diese entspricht: „auswählen ... Von A Inner Join B auf (A.id = B.a_id), C, D, F, wo A. id = F.id " zu: " Wählen Sie ... Von einem inneren Join B auf (A.id = B.a_id), C, D INNER JOIN F auf A.id = F.a_id " Eigentlich ist die Hauptfrage, dass F eine Verknüpfung nicht mit D hat, aber mit A, und A tritt viel früher im Ausdruck auf, also funktioniert die Inner Join korrekt, um die beiden Fälle zu reduzieren, um dieselbe Ergebnismenge zurückzugeben? – umar

1

Ja, und Sie könnten auch einfach

"Where PK Is Not Null" or 
"Where FK Is Not Null" 

hinzufügen und dies würde auch die „extra“ Datensätze aus der „äußeren“ Seite des Joins herauszufiltern ...