1125 Stimmen

INNER JOIN ON vs WHERE-Klausel

Der Einfachheit halber nehmen wir an, dass alle relevanten Felder NOT NULL .

Das können Sie 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)

Funktionieren diese beiden auf dieselbe Weise in MySQL ?

2 Stimmen

@Marco: hier ist es

2 Stimmen

32 Stimmen

Wenn ich es richtig verstanden habe, handelt es sich bei der ersten Variante um die implizite ANSI-SQL-89-Syntax und bei der zweiten Variante um die explizite ANSI-SQL-92-Join-Syntax. Beide führen in konformen SQL-Implementierungen zum gleichen Ergebnis und beide führen in gut gemachten SQL-Implementierungen zum gleichen Abfrageplan. Ich persönlich bevorzuge die SQL-89-Syntax, aber viele Leute bevorzugen die SQL-92-Syntax.

796voto

Quassnoi Punkte 396418

INNER JOIN ist die ANSI-Syntax, die Sie verwenden sollten.

Sie wird im Allgemeinen als besser lesbar angesehen, insbesondere wenn Sie viele Tabellen verbinden.

Sie kann auch leicht durch eine OUTER JOIN wann immer ein Bedarf entsteht.

El WHERE Die Syntax ist eher am relationalen Modell orientiert.

Ein Ergebnis von zwei Tabellen JOIN ed ist ein kartesisches Produkt der Tabellen, auf die ein Filter angewendet wird, der nur die Zeilen auswählt, deren Verbindungsspalten übereinstimmen.

Es ist einfacher, dies zu sehen, wenn die WHERE Syntax.

Was Ihr Beispiel betrifft, so sind diese beiden Abfragen in MySQL (und in SQL allgemein) Synonyme.

Beachten Sie außerdem, dass MySQL auch eine STRAIGHT_JOIN Klausel.

Mit dieser Klausel können Sie die JOIN Reihenfolge: welche Tabelle wird in der äußeren Schleife und welche in der inneren Schleife durchsucht.

Sie können dies in MySQL nicht kontrollieren, indem Sie WHERE Syntax.

233voto

Carl Manaster Punkte 38966

Andere haben darauf hingewiesen, dass INNER JOIN trägt zur Lesbarkeit bei, und das hat höchste Priorität, da stimme ich zu.
Lassen Sie mich versuchen zu erklären pourquoi die Join-Syntax ist besser lesbar.

Eine grundlegende SELECT Frage ist diese:

SELECT stuff
FROM tables
WHERE conditions

El SELECT Klausel sagt uns ce que die wir zurückbekommen; die FROM Klausel sagt uns wobei wir sie bekommen, und die WHERE Klausel sagt uns die die wir bekommen.

JOIN ist eine Aussage über die Tabellen, wie sie miteinander verbunden sind (konzeptionell, tatsächlich zu einer einzigen Tabelle).

Alle Abfrageelemente, die die Tabellen steuern - aus denen wir die Daten beziehen - gehören semantisch zur FROM Klausel (und das ist natürlich der Punkt, an dem JOIN Elemente gehen). Das Einfügen von Verbindungselementen in die WHERE Klausel verschmilzt die die und die woher Deshalb ist die JOIN Syntax bevorzugt wird.

167voto

rafidheen Punkte 1683

Anwendung von bedingten Anweisungen in ON / WHERE

Hier habe ich die Schritte der logischen Abfrageverarbeitung erläutert.


Referenz: T-SQL-Abfragen in Microsoft® SQL Server™ 2005
Herausgeber: Microsoft Press
Veröffentlichungsdatum: März 07, 2006
Drucken ISBN-10: 0-7356-2313-9
Gedruckt ISBN-13: 978-0-7356-2313-2
Seiten: 640

Einblick in Microsoft® SQL Server™ 2005 T-SQL-Abfragen

(8)  SELECT (9) DISTINCT (11) TOP <top_specification> <select_list>
(1)  FROM <left_table>
(3)       <join_type> JOIN <right_table>
(2)       ON <join_condition>
(4)  WHERE <where_condition>
(5)  GROUP BY <group_by_list>
(6)  WITH {CUBE | ROLLUP}
(7)  HAVING <having_condition>
(10) ORDER BY <order_by_list>

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 wird. In SQL wird als erstes die FROM-Klausel verarbeitet, während die SELECT-Klausel, die an erster Stelle steht, fast zuletzt verarbeitet wird.

Jeder Schritt erzeugt eine virtuelle Tabelle, die als Eingabe für den nächsten Schritt verwendet wird. Diese virtuellen Tabellen sind für den Aufrufer (Client-Anwendung oder äußere Abfrage) nicht verfügbar. Nur die vom letzten Schritt erzeugte Tabelle wird an den Aufrufer zurückgegeben. Wenn eine bestimmte Klausel in einer Abfrage nicht angegeben ist, wird der entsprechende Schritt einfach übersprungen.

Kurzbeschreibung der Phasen der logischen Abfrageverarbeitung

Machen Sie sich nicht zu viele Sorgen, wenn die Beschreibung der Schritte im Moment nicht viel Sinn zu machen scheint. Sie sind als Referenz gedacht. In den Abschnitten, die nach dem Beispielszenario folgen, werden die Schritte viel ausführlicher behandelt.

  1. VON: Zwischen den ersten beiden Tabellen in der FROM-Klausel wird ein kartesisches Produkt (Cross-Join) gebildet, und als Ergebnis wird die virtuelle Tabelle VT1 erstellt.

  2. ON: Der Filter ON wird auf VT1 angewendet. Nur Zeilen, für die der <join_condition> TRUE ist, werden in VT2 eingefügt.

  3. OUTER (join): Wenn ein OUTER JOIN angegeben ist (im Gegensatz zu einem CROSS JOIN oder einem INNER JOIN), werden Zeilen aus der erhaltenen Tabelle oder den erhaltenen Tabellen, für die keine Übereinstimmung gefunden wurde, zu den Zeilen aus VT2 als äußere Zeilen hinzugefügt, wodurch VT3 entsteht. Wenn mehr als zwei Tabellen in der FROM-Klausel erscheinen, werden die Schritte 1 bis 3 wiederholt zwischen dem Ergebnis der letzten Verknüpfung und der nächsten Tabelle in der FROM-Klausel angewendet, bis alle Tabellen verarbeitet sind.

  4. WO: Der WHERE-Filter wird auf VT3 angewendet. Nur Zeilen, für die der <where_condition> TRUE ist, werden in VT4 eingefügt.

  5. GROUP BY: Die Zeilen aus VT4 werden auf der Grundlage der in der GROUP BY-Klausel angegebenen Spaltenliste in Gruppen angeordnet. VT5 wird erzeugt.

  6. CUBE | ROLLUP: Supergruppen (Gruppen von Gruppen) werden zu den Zeilen von VT5 hinzugefügt und erzeugen VT6.

  7. HAVING: Der HAVING-Filter wird auf VT6 angewendet. Nur Gruppen, für die der <having_condition> TRUE ist, werden in VT7 eingefügt.

  8. SELECT: Die SELECT-Liste wird abgearbeitet und erzeugt VT8.

  9. DISTINCT: Doppelte Zeilen werden aus VT8 entfernt. VT9 wird erzeugt.

  10. ORDER BY: Die Zeilen aus VT9 werden nach der in der ORDER BY-Klausel angegebenen Spaltenliste sortiert. Es wird ein Cursor erzeugt (VC10).

  11. TOP: Die angegebene Anzahl oder der angegebene Prozentsatz von Zeilen wird ab dem Anfang von VC10 ausgewählt. Die Tabelle VT11 wird erstellt und an den Aufrufer zurückgegeben.


Daher werden die Daten vor der Anwendung der WHERE-Klausel durch (INNER JOIN) ON gefiltert (die Datenanzahl von VT wird hier selbst reduziert). Die nachfolgenden Join-Bedingungen werden mit gefilterten Daten ausgeführt, was die Leistung verbessert. Danach wendet nur noch die WHERE-Bedingung Filterbedingungen an.

(Die Anwendung von bedingten Anweisungen in ON / WHERE wird in wenigen Fällen keinen großen Unterschied machen. Dies hängt davon ab, wie viele Tabellen Sie verbunden haben und wie viele Zeilen in den einzelnen Verbindungstabellen verfügbar sind.)

80voto

Cade Roux Punkte 85601

Die ANSI-Syntax für implizite Verknüpfungen 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 die INNER JOIN also auch INNER JOIN Abfragen mit WHERE Klauseln können die Prädikate durch den Optimierer neu angeordnet werden.

Ich empfehle Ihnen, die Abfragen so lesbar wie möglich zu schreiben.

Dazu gehört manchmal auch, dass die INNER JOIN relativ "unvollständig" zu sein und einige der Kriterien in die WHERE um die Listen der Filterkriterien leichter pflegen zu können.

Zum Beispiel anstelle von:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

Schreiben:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

Aber es kommt natürlich darauf an.

39voto

matt b Punkte 135206

Implizite Verknüpfungen (als die Ihre erste Abfrage bekannt ist) werden sehr viel verwirrender, schwer zu lesen und schwer zu pflegen, wenn Sie anfangen müssen, weitere Tabellen zu Ihrer Abfrage hinzuzufügen. Stellen Sie sich vor, Sie müssten dieselbe Abfrage und dieselbe Art von Verknüpfung für vier oder fünf verschiedene Tabellen durchführen ... ein Albtraum.

Die Verwendung einer expliziten Verknüpfung (Ihr zweites Beispiel) ist viel lesbarer und leichter zu pflegen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X