it-swarm.dev

Verwenden Sie das Schlüsselwort JOIN oder nicht

Die folgenden SQL-Abfragen sind identisch:

SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;

SELECT column1, column2
FROM table1 JOIN table2 
ON table1.id = table2.id;

Und sicherlich führen Sie zu denselben Abfrageplänen für jedes DBMS, das ich jemals ausprobiert habe.

Aber hin und wieder lese oder höre ich eine Meinung, dass einer definitiv besser ist als der andere. Natürlich werden diese Behauptungen niemals mit einer Erklärung belegt.

Wo ich arbeite, scheint die zweite Version von den meisten anderen Entwicklern bevorzugt zu werden, und deshalb tendiere ich auch zu diesem Stil, um Überraschungen zu minimieren. Aber in meinem Herzen denke ich wirklich an den ersten (da ich ihn ursprünglich so gelernt habe).

Ist eine dieser Formen objektiv besser als die andere? Wenn nicht, was wären die Gründe, einen über den anderen zu verwenden?

Ich finde, dass die zweite Form besser ist. Das mag daran liegen, dass ich es so gelernt habe, gebe ich zu, aber ich habe einen konkreten Grund - die Trennung von Bedenken. Das Einfügen der Felder, die Sie zum Verknüpfen der Tabellen in die where-Klausel verwenden, kann zu Schwierigkeiten beim Verstehen von Abfragen führen.

Nehmen Sie zum Beispiel die folgende Abfrage:

select *
from table1, table2, table3, table4
where table1.id = table2.id
and table2.id = table3.id
and table3.id = table4.id
and table1.column1 = 'Value 1'

Die obige Abfrage enthält Tabellenverbindungsbedingungen und tatsächliche Geschäftslogikbedingungen, die alle in einem einzigen Bereich zusammengefasst sind. Bei einer großen Abfrage kann dies sehr schwer zu verstehen sein.

Nehmen Sie jetzt jedoch diesen Code:

select *
from table1 join table2 on table1.id = table2.id
join table3 on table2.id = table3.id
join table4 on table3.id = table4.id
where table1.column1 = 'Value 1'

In diesem Fall ist alles, was mit den Tabellen zu tun hat oder wie sie sich beziehen, auf die from-Klausel isoliert, während sich die eigentliche Geschäftslogik für die Abfrageeinschränkung in der where-Klausel befindet. Ich denke, das ist gerade für größere Anfragen viel verständlicher.

62
Dustin Wilhelmi

Die Join-Syntax ersetzte 1992 die alte Kommasyntax. Derzeit gibt es keinen Grund, jemals Code mit der Kommasyntax zu schreiben. Sie gewinnen nichts und haben einige Probleme, die Sie mit der expliziten Syntax einfach nicht haben.

Erstens ist es bei komplizierteren Abfragen sehr einfach, einen versehentlichen Cross-Join durchzuführen, indem eine where-Bedingung fehlt. Dies kann durch die explizite Verknüpfungssyntax verhindert werden, da ein Syntaxfehler angezeigt wird.

Wenn Sie einen Cross-Join beabsichtigen, wird dies durch die explizite Join-Syntax deutlich, während in der impliziten Syntax möglicherweise jemand, der die Wartung durchführt, davon ausgeht, dass Sie vergessen haben, die where-Klausel hinzuzufügen.

Dann gibt es das Problem der Links- und Rechtsverknüpfungen, die zumindest in einigen DBs unter Verwendung der impliziten Syntax problematisch sind. Sie sind in SQL Server veraltet und liefern selbst in älteren Versionen nicht wirklich die richtigen Ergebnisse. Keine Abfrage, die einen Outer Join benötigt, sollte die implizite Syntax in SQL Server enthalten.

Außerdem habe ich hier und auf anderen Websites Fragen gesehen, bei denen beim Mischen der impliziten und expliziten Verknüpfungen (z. B. beim Hinzufügen einer linken Verknüpfung) falsche Ergebnisse aufgetreten sind. Daher ist es eine schlechte Idee, diese zu mischen.

Schließlich verstehen viele Leute, die implizite Verknüpfungen verwenden, Verknüpfungen nicht wirklich. Dies ist ein kritisches Verständnis, das Sie benötigen, um eine Datenbank effektiv abzufragen.

40
HLGEM

Ha. Ich habe gerade eine mögliche Antwort auf meine eigene Frage gefunden, als ich mir die Dokumentation für PostgreSQL angesehen habe. Um zusammenzufassen, was auf dieser Seite erklärt wird, ist die resultierende Abfrage immer noch dieselbe, aber die Anzahl der Pläne , die der Optimierer berücksichtigen muss, wächst exponentiell mit der Anzahl der Verknüpfungen.

Nach ungefähr sechs solchen Verknüpfungen ist die Anzahl so groß, dass die Zeit zum Planen der Abfrage möglicherweise spürbar ist, und nach ungefähr zehn wechselt der Optimierer von einer umfassenden Suche nach Plänen zu einer probabilistischen Suche und gelangt möglicherweise nicht zum optimalen Plan .

Durch Festlegen eines Laufzeitparameters können Sie den Planer anweisen, explizit erwähnte innere und Kreuzverknüpfungen anders als implizite Verknüpfungen zu behandeln, sie an den Anfang des Plans zu zwingen und andere Optionen nicht zu untersuchen.

Zu beachten ist, dass das Standardverhalten in beiden Fällen das gleiche ist und dass für das Abrufen alternativer Pläne die Interna der Datenbank und die Besonderheiten der betreffenden Tabellen bekannt sein müssen, um ein anderes Ergebnis zu erzielen

Nun, hier ist die Ansicht der Mengenlehre:

Wenn Sie zwei (oder mehr) Tabellennamen durch ein Komma trennen, ist das kartesische Produkt beabsichtigt. Jede Zeile der 'linken' Tabelle wird mit der der rechten Tabelle 'abgeglichen' (verkettet).

Wenn Sie nun etwas in die where-Klausel schreiben, ist es so, als würden Sie eine Bedingung für diese "Verkettung" festlegen, die angibt, welche Zeilen mit welchen Zeilen "verkettet" werden sollen.

Dies ist eigentlich das "Verbinden" der Zeilen :) und damit das Join-Schlüsselwort, das eine besser lesbare Syntax bietet und verständlicher ist, dass Sie tatsächlich einige gemeinsame Werte verbinden möchten. Ähnlich wie @Dustin oben klargestellt hat.

Jetzt ist jedes DBMS intelligent, d. H. Es berechnet nicht zuerst das kartesische Produkt und filtert dann die Daten heraus (äußerst verschwenderisch), sondern basiert auf der Abfragestruktur. Das einzige, woran ich denken kann, ist, wenn Sie ihn zum "Beitreten" auffordern, dass Sie die Beitrittsaktivität explizit machen und wahrscheinlich dazu beitragen, den Code schneller auszuführen (um wie viel? Sie müssen ihn profilieren und sehen), aber in der Durch Kommas getrennte Groß- und Kleinschreibung wird einige Zeit benötigt, um die optimale Strategie zu ermitteln. Ich kann mich irren, aber ich mache nur eine fundierte Vermutung, wie man es codieren würde ...

8
PhD

Ich denke, es ist im Allgemeinen besser, JOIN-Anweisungen für diesen Fall zu verwenden.

Wenn in Zukunft eine Situation auftritt, in der die Anweisung von INNER JOIN in OUTER JOIN geändert werden muss, ist dies mit der zweiten Anweisung viel einfacher.

5
Britt Wescott

Jedes RDBMS wird dazu führen, dass sie in Bezug auf die Ausführung dasselbe sind. Es kommt darauf an, ob man lesbarer und ausdrucksvoller ist.

Verwenden Sie JOIN, damit klar ist, was Join-Matching und was tatsächliche Auswahl ist, wie in:

select name, deptname
from people p, departments d
where p.deptid = d.id and p.is_temp = 'Y'

vs.

select name, deptname
from people p
    inner join departments d on p.deptid = d.id
where p.is_temp = 'Y'

Der letztere Fall macht sofort klar, welche die Verbindungsbedingung und welches das Auswahlkriterium ist.

3
Andy Lester

Ich habe nur einmal gesehen, dass die beiden zu unterschiedlichen Optimierungen führen, und wenn Speicher dient, war es in ms-sql2k bei einer wirklich haarigen Abfrage. In diesem einen Beispiel führte die alte Form, die mit * = verwendet wurde, zu einer etwa viermal schnelleren Leistung. Niemand, einschließlich unserer Microsoft-Techniker, konnte jemals erklären, warum. Die MS-Leute haben es als Fehler bezeichnet. Ich habe es nie wieder gesehen.

Da die meisten RDBMS klug genug sind, nicht die vollen Kartesier zu machen, ist der größte Grund, warum ich daran denken kann, es nicht zu verwenden (abgesehen davon, dass es abgeschrieben wird), dass die meisten Leute unter 30-35, mit denen ich gearbeitet habe, das noch nie gesehen haben alte Form vor und verlieren sich schrecklich, wenn sie darauf stoßen.

1
Bill