Nehmen Sie der Einfachheit halber an, dass alle relevanten Felder sind NOT NULL
.
Du kannst tun:
SELECT
table1.this, table2.that, table2.somethingelse
FROM
table1, table2
WHERE
table1.foreignkey = table2.primarykey
AND (some other conditions)
Oder aber:
SELECT
table1.this, table2.that, table2.somethingelse
FROM
table1 INNER JOIN table2
ON table1.foreignkey = table2.primarykey
WHERE
(some other conditions)
Arbeiten diese beiden auf die gleiche Weise MySQL
?
sql
mysql
join
inner-join
JCCyC
quelle
quelle
Antworten:
INNER JOIN
ist die ANSI-Syntax, die Sie verwenden sollten.Es wird im Allgemeinen als besser lesbar angesehen, insbesondere wenn Sie viele Tabellen verbinden.
Es kann auch leicht durch ein ersetzt werden,
OUTER JOIN
wenn ein Bedarf entsteht.Die
WHERE
Syntax ist eher relational modellorientiert.Das Ergebnis von zwei Tabellen
JOIN
ed ist ein kartesisches Produkt der Tabellen, auf die ein Filter angewendet wird, der nur die Zeilen mit übereinstimmenden Verbindungsspalten auswählt.Mit der
WHERE
Syntax ist dies einfacher zu erkennen .In MySQL (und allgemein in SQL) sind diese beiden Abfragen Synonyme.
Beachten Sie auch, dass MySQL auch eine
STRAIGHT_JOIN
Klausel enthält.Mit dieser Klausel können Sie die
JOIN
Reihenfolge steuern : Welche Tabelle wird in der äußeren Schleife gescannt und welche in der inneren Schleife.Sie können dies in MySQL nicht mithilfe der
WHERE
Syntax steuern .quelle
Oracle
,SQL Server
,MySQL
undPostgreSQL
- ja. Wahrscheinlich auch für andere Systeme, aber Sie sollten dies besser überprüfen.WHERE
Klausel, ist ebenfalls im ANSI-Standard enthalten.@Bill Karwin
: DasJOIN
Schlüsselwort war bis in die Vergangenheit nicht Teil proprietärer Standards, wie es scheint. Es hat seinen WegOracle
nur in in Version9
und inPostgreSQL
in Version7.2
(beide veröffentlicht in2001
) gemacht. Das Auftreten dieses Schlüsselworts war Teil derANSI
Standardakzeptanz, und deshalb wird dieses Schlüsselwort normalerweise mit assoziiertANSI
, obwohl letzteres auch Komma als Synonym für unterstütztCROSS JOIN
.WHERE
Verknüpfungen mit Kommas und Bedingungen in einer Klausel ausgeführt werden sollen (ohne Bedingungen entspricht eine Verknüpfung, wie Sie sagten, einer Kreuzverknüpfung). ANSI SQL-92 hat dasJOIN
Schlüsselwort und die zugehörige Syntax hinzugefügt, die Syntax im Kommastil wird jedoch aus Gründen der Abwärtskompatibilität weiterhin unterstützt.Andere haben darauf hingewiesen, dass dies
INNER JOIN
die Lesbarkeit des Menschen verbessert, und das stimmt, da stimme ich zu.Lassen Sie mich versuchen zu erklären, warum die Join-Syntax besser lesbar ist.
Eine grundlegende
SELECT
Abfrage lautet wie folgt:Die
SELECT
Klausel sagt uns, was wir zurückbekommen; DieFROM
Klausel sagt uns, woher wir es bekommen, und dieWHERE
Klausel sagt uns, welche wir bekommen.JOIN
ist eine Aussage über die Tabellen, wie sie miteinander verbunden sind (konzeptionell tatsächlich in einer einzigen Tabelle).Alle Abfrageelemente, die die Tabellen steuern - von denen wir Material beziehen - gehören semantisch zur
FROM
Klausel (und natürlichJOIN
gehen dort Elemente hin). Putting Verbindungselemente in dieWHERE
Klausel verschmilzt die das und das , wo-aus , deshalb dieJOIN
Syntax bevorzugt.quelle
Anwenden von bedingten Anweisungen in ON / WHERE
Hier habe ich die logischen Abfrageverarbeitungsschritte erklärt.
Referenz: In Microsoft® SQL Server ™ 2005 T-SQL-Abfrage
Herausgeber: Microsoft Press Veröffentlichungsdatum:
07. März 2006
Drucken Sie ISBN-10: 0-7356-2313-9
Drucken Sie ISBN-13: 978-0-7356-2313-2
Seiten: 640
In Microsoft® SQL Server ™ 2005 T-SQL-Abfrage
Der erste auffällige Aspekt von SQL, der sich von anderen Programmiersprachen unterscheidet, ist die Reihenfolge, in der der Code verarbeitet wird. In den meisten Programmiersprachen wird der Code in der Reihenfolge verarbeitet, in der er geschrieben wurde. In SQL ist die erste Klausel, die verarbeitet wird, die FROM-Klausel, während die SELECT-Klausel, die zuerst angezeigt wird, fast zuletzt verarbeitet wird.
Jeder Schritt generiert eine virtuelle Tabelle, die als Eingabe für den folgenden Schritt verwendet wird. Diese virtuellen Tabellen stehen dem Aufrufer nicht zur Verfügung (Clientanwendung oder äußere Abfrage). Nur die vom letzten Schritt generierte Tabelle wird an den Aufrufer zurückgegeben. Wenn in einer Abfrage keine bestimmte Klausel angegeben ist, wird der entsprechende Schritt einfach übersprungen.
Kurze Beschreibung der Phasen der Verarbeitung logischer Abfragen
Machen Sie sich nicht zu viele Sorgen, wenn die Beschreibung der Schritte vorerst nicht viel Sinn macht. Diese dienen als Referenz. Abschnitte, die nach dem Szenariobeispiel folgen, werden die Schritte ausführlicher behandeln.
FROM: Ein kartesisches Produkt (Cross Join) wird zwischen den ersten beiden Tabellen in der FROM-Klausel ausgeführt, und als Ergebnis wird die virtuelle Tabelle VT1 generiert.
EIN: Der EIN-Filter wird auf VT1 angewendet. Nur Zeilen, für die
<join_condition>
TRUE ist, werden in VT2 eingefügt.OUTER (Join): Wenn ein OUTER JOIN angegeben ist (im Gegensatz zu einem CROSS JOIN oder einem INNER JOIN), werden Zeilen aus der oder den erhaltenen Tabellen oder Tabellen, für die keine Übereinstimmung gefunden wurde, als äußere Zeilen zu den Zeilen von VT2 hinzugefügt VT3. Wenn in der FROM-Klausel mehr als zwei Tabellen enthalten sind, werden die Schritte 1 bis 3 zwischen dem Ergebnis des letzten Joins und der nächsten Tabelle in der FROM-Klausel wiederholt angewendet, bis alle Tabellen verarbeitet sind.
WHERE: Der WHERE-Filter wird auf VT3 angewendet. Nur Zeilen, für die
<where_condition>
TRUE ist, werden in VT4 eingefügt.GROUP BY: Die Zeilen von VT4 sind basierend auf der in der GROUP BY-Klausel angegebenen Spaltenliste in Gruppen angeordnet. VT5 wird generiert.
WÜRFEL | ROLLUP: Supergruppen (Gruppen von Gruppen) werden zu den Zeilen von VT5 hinzugefügt, wodurch VT6 generiert wird.
HAVING: Der HAVING-Filter wird auf VT6 angewendet. Nur Gruppen, für die
<having_condition>
TRUE ist, werden in VT7 eingefügt.SELECT: Die SELECT-Liste wird verarbeitet und generiert VT8.
DISTINCT: Doppelte Zeilen werden aus VT8 entfernt. VT9 wird generiert.
ORDER BY: Die Zeilen von VT9 werden gemäß der in der ORDER BY-Klausel angegebenen Spaltenliste sortiert. Ein Cursor wird erzeugt (VC10).
TOP: Die angegebene Anzahl oder der angegebene Prozentsatz der Zeilen wird ab dem Beginn von VC10 ausgewählt. Tabelle VT11 wird generiert und an den Anrufer zurückgegeben.
Daher filtert (INNER JOIN) ON die Daten (die Datenanzahl von VT wird hier selbst reduziert), bevor die WHERE-Klausel angewendet wird. Die nachfolgenden Verknüpfungsbedingungen werden mit gefilterten Daten ausgeführt, wodurch die Leistung verbessert wird. Danach wendet nur die WHERE-Bedingung Filterbedingungen an.
(Das Anwenden von bedingten Anweisungen in ON / WHERE macht in einigen Fällen keinen großen Unterschied. Dies hängt davon ab, wie viele Tabellen Sie verbunden haben und wie viele Zeilen in jeder Verknüpfungstabelle verfügbar sind.)
quelle
Die implizite Join-ANSI-Syntax ist älter, weniger offensichtlich und wird nicht empfohlen.
Darüber hinaus ermöglicht die relationale Algebra die Austauschbarkeit der Prädikate in der
WHERE
Klausel und derINNER JOIN
, sodass selbst beiINNER JOIN
Abfragen mitWHERE
Klauseln die Prädikate vom Optimierer neu angeordnet werden können.Ich empfehle Ihnen, die Abfragen so gut wie möglich zu schreiben.
Manchmal beinhaltet dies das
INNER JOIN
relativ "unvollständige" und das Einfügen einiger Kriterien inWHERE
die Liste, um die Liste der Filterkriterien einfacher zu pflegen.Zum Beispiel anstelle von:
Schreiben:
Aber es kommt natürlich darauf an.
quelle
Implizite Verknüpfungen (wie Ihre erste Abfrage genannt wird) werden viel verwirrender, schwer lesbar und schwer zu pflegen, sobald Sie Ihrer Abfrage weitere Tabellen hinzufügen müssen. Stellen Sie sich vor, Sie führen dieselbe Abfrage und denselben Join-Typ für vier oder fünf verschiedene Tabellen durch ... es ist ein Albtraum.
Die Verwendung eines expliziten Joins (Ihr zweites Beispiel) ist viel besser lesbar und einfach zu warten.
quelle
Ich werde auch darauf hinweisen, dass die Verwendung der älteren Syntax eher fehleranfällig ist. Wenn Sie innere Verknüpfungen ohne ON-Klausel verwenden, wird ein Syntaxfehler angezeigt. Wenn Sie die ältere Syntax verwenden und eine der Join-Bedingungen in der where-Klausel vergessen, erhalten Sie einen Cross-Join. Die Entwickler beheben dies häufig, indem sie das eindeutige Schlüsselwort hinzufügen (anstatt den Join zu reparieren, da sie immer noch nicht erkennen, dass der Join selbst beschädigt ist). Dies scheint das Problem zu beheben, verlangsamt jedoch die Abfrage erheblich.
Woher weiß der Betreuer bei Wartungsarbeiten, wenn Sie einen Cross-Join in der alten Syntax haben, ob Sie einen haben wollten (es gibt Situationen, in denen Cross-Joins erforderlich sind) oder ob es sich um einen Unfall handelte, der behoben werden sollte?
Lassen Sie mich auf diese Frage hinweisen, um zu sehen, warum die implizite Syntax schlecht ist, wenn Sie linke Verknüpfungen verwenden. Sybase * = nach Ansi Standard mit 2 verschiedenen äußeren Tabellen für dieselbe innere Tabelle
Außerdem ist der Standard, der die expliziten Verknüpfungen verwendet, über 20 Jahre alt, was bedeutet, dass die implizite Verknüpfungssyntax für diese 20 Jahre veraltet ist. Würden Sie Anwendungscode mit einer Syntax schreiben, die seit 20 Jahren veraltet ist? Warum möchten Sie also Datenbankcode schreiben?
quelle
HAVING
das veraltet ist, seit SQL abgeleitete Tabellen unterstützt. Ich stelle auch fest, dass Sie nicht verwendenNATURAL JOIN
, obwohl ich behaupten würde, dass esINNER JOIN
"veraltet" ist. Ja, Sie haben Ihre Gründe (Sie müssen sie hier nicht noch einmal angeben!): Mein Punkt ist, dass diejenigen, die gerne die ältere Syntax verwenden, auch ihre Gründe haben und das relative Alter der Syntax von geringer oder gar keiner Relevanz ist.Sie haben eine andere vom Menschen lesbare Bedeutung.
Abhängig vom Abfrageoptimierer haben sie jedoch möglicherweise dieselbe Bedeutung für den Computer.
Sie sollten immer Code verwenden, um lesbar zu sein.
Das heißt, wenn dies eine integrierte Beziehung ist, verwenden Sie den expliziten Join. Wenn Sie mit schwach verwandten Daten übereinstimmen, verwenden Sie die where-Klausel.
quelle
Der SQL: 2003-Standard hat einige Vorrangregeln geändert, sodass eine JOIN-Anweisung Vorrang vor einem "Komma" -Verbindung hat. Dies kann die Ergebnisse Ihrer Abfrage abhängig von der Einrichtung tatsächlich ändern. Dies verursacht für einige Leute einige Probleme, als MySQL 5.0.12 auf die Einhaltung des Standards umstellte.
In Ihrem Beispiel würden Ihre Abfragen also genauso funktionieren. Wenn Sie jedoch eine dritte Tabelle hinzugefügt haben: SELECT ... FROM table1, table2 JOIN table3 ON ... WHERE ...
Vor MySQL 5.0.12 wurden zuerst Tabelle1 und Tabelle2 und dann Tabelle3 verbunden. Jetzt (5.0.12 und höher) werden zuerst Tabelle2 und Tabelle3 verbunden, dann Tabelle1. Es ändert nicht immer die Ergebnisse, aber es kann und Sie können es nicht einmal realisieren.
Ich verwende nie mehr die "Komma" -Syntax und entscheide mich für Ihr zweites Beispiel. Es ist sowieso viel besser lesbar, die JOIN-Bedingungen gelten für die JOINs und sind nicht in einen separaten Abfrageabschnitt unterteilt.
quelle
Ich weiß, dass Sie über MySQL sprechen, aber trotzdem: In Oracle 9 würden explizite und implizite Verknüpfungen unterschiedliche Ausführungspläne generieren. AFAIK, das in Oracle 10+ gelöst wurde: Es gibt keinen solchen Unterschied mehr.
quelle
Die ANSI-Join-Syntax ist definitiv portabler.
Ich mache ein Upgrade von Microsoft SQL Server durch und möchte auch erwähnen, dass die Syntax = * und * = für äußere Verknüpfungen in SQL Server für 2005 SQL Server und höher nicht unterstützt wird (ohne Kompatibilitätsmodus).
quelle
*=
und=*
waren nie ANSI und waren nie eine gute Notation. Aus diesem Grund wurde ON benötigt - für OUTER JOINs ohne Unterauswahl (die gleichzeitig hinzugefügt wurden, sodass sie in CROSS & INNER JOINs nicht benötigt werden.)Wenn Sie häufig dynamische gespeicherte Prozeduren programmieren, werden Sie sich in Ihr zweites Beispiel verlieben (mit where). Wenn Sie verschiedene Eingabeparameter und viel Morph-Chaos haben, ist dies der einzige Weg. Andernfalls führen beide denselben Abfrageplan aus, sodass bei klassischen Abfragen definitiv kein offensichtlicher Unterschied besteht.
quelle