SQL beitreten: where-Klausel gegen on-Klausel

stimmen
483

Nach der Lektüre, dann ist dies nicht ein Duplikat Explicit vs Implizite SQL Joins . Die Antwort kann in Beziehung gesetzt werden (oder sogar die gleichen) , aber die Frage ist anders.


Was ist der Unterschied und was in jedem gehen sollte?

Wenn ich die Theorie richtig zu verstehen, sollte der Abfrageoptimierer der Lage sein, beide austauschbar zu verwenden.

Veröffentlicht am 09/12/2008 um 21:14
quelle vom benutzer
In anderen Sprachen...                            


14 antworten

stimmen
640

Sie sind nicht das Gleiche.

Betrachten Sie diese Anfragen:

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345

und

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID 
    AND Orders.ID = 12345

Der erste wird einen Auftrag und seine Linien zurückzukehren, falls vorhanden, für die Auftragsnummer 12345. Der zweite wird alle Aufträge zurück, aber nur , um 12345alle Zeilen mit ihm verbunden wird.

Mit INNER JOINsind die Klauseln wirksam gleichwertig. Allerdings nur , weil sie sind funktionell gleich, dass sie die gleichen Ergebnisse liefern, nicht die zwei Arten von Klauseln bedeutet die gleiche semantische Bedeutung haben.

Beantwortet am 09/12/2008 um 21:21
quelle vom benutzer

stimmen
154
  • Spielt keine Rolle für innere Joins
  • Matters für Outer-Joins

    ein. WHEREKlausel: Nach dem Beitritt. Aufzeichnungen werden nach gefiltert werden join stattgefunden hat.

    b. ONKlausel - Vor dem Beitritt. Aufzeichnungen (von rechts Tabelle) werden , bevor er gefiltert werden. Dies kann als Null in der Folge am Ende (seit OUTER JOIN).



Beispiel : Betrachten Sie die folgenden Tabellen:

    1. documents:
     | id    | name        |
     --------|-------------|
     | 1     | Document1   |
     | 2     | Document2   |
     | 3     | Document3   |
     | 4     | Document4   |
     | 5     | Document5   |


    2. downloads:
     | id   | document_id   | username |
     |------|---------------|----------|
     | 1    | 1             | sandeep  |
     | 2    | 1             | simi     |
     | 3    | 2             | sandeep  |
     | 4    | 2             | reya     |
     | 5    | 3             | simi     |

a) Innerhalb WHEREKlausel:

  SELECT documents.name, downloads.id
    FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
    WHERE username = 'sandeep'

 For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 1                  | Document1    | 2                   | 1           | simi     |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 2                  | Document2    | 4                   | 2           | reya     |
    | 3                  | Document3    | 5                   | 3           | simi     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

  After applying the `WHERE` clause and selecting the listed attributes, the result will be: 

   | name         | id |
   |--------------|----|
   | Document1    | 1  |
   | Document2    | 3  | 

b) Innerhalb JOINKlausel

  SELECT documents.name, downloads.id
  FROM documents
    LEFT OUTER JOIN downloads
      ON documents.id = downloads.document_id
        AND username = 'sandeep'

For above query the intermediate join table will look like this.

    | id(from documents) | name         | id (from downloads) | document_id | username |
    |--------------------|--------------|---------------------|-------------|----------|
    | 1                  | Document1    | 1                   | 1           | sandeep  |
    | 2                  | Document2    | 3                   | 2           | sandeep  |
    | 3                  | Document3    | NULL                | NULL        | NULL     |
    | 4                  | Document4    | NULL                | NULL        | NULL     |
    | 5                  | Document5    | NULL                | NULL        | NULL     |

Notice how the rows in `documents` that did not match both the conditions are populated with `NULL` values.

After Selecting the listed attributes, the result will be: 

   | name       | id   |
   |------------|------|
   |  Document1 | 1    |
   |  Document2 | 3    | 
   |  Document3 | NULL |
   |  Document4 | NULL | 
   |  Document5 | NULL | 
Beantwortet am 07/01/2014 um 21:54
quelle vom benutzer

stimmen
137

Auf INNER JOINs sie sind untereinander austauschbar, und das Optimierungsprogramm wird sie nach Belieben neu anordnen.

Auf OUTER JOINs, sind sie nicht unbedingt austauschbar sind , je nachdem , welche Seite des verbinden sie abhängig sind.

Ich habe sie in jedem Ort, in Abhängigkeit von der Lesbarkeit.

Beantwortet am 09/12/2008 um 21:21
quelle vom benutzer

stimmen
30

So wie ich es tun ist:

Setzen Sie immer die Bedingungen in der auf Join-Klausel Wenn Sie eine innere Verknüpfung tun, so fügen Sie keine wo die Bedingungen auf der on-Klausel, legte sie in der where-Klausel

Wenn Sie ein LEFT JOIN tun, fügen Sie alle, wo die Bedingungen an den on-Klausel für die Tabelle in der rechten Seite des Joins. Dies ist ein Muss, weil das Hinzufügen einer where-Klausel, die die rechte Seite der Verknüpfung verweist wandelt den Join eine innere Verknüpfung (mit einer Ausnahme unten beschrieben).

Die Ausnahme ist, dass, wenn Sie für die Datensätze suchen, der nicht in einer bestimmten Tabelle sind, würden Sie die refernce zu einer eindeutigen Kennung hinzufügen (das ist nicht immer null) in den rechten Join-Tabelle auf die Klausel in dem auf diese Weise „Wo t2. idfield ist null“. Also das einzige Mal, sollten Sie eine Tabelle auf der rechten Seite Referenz der Verbindung ist die Datensätze zu finden, die nicht in der Tabelle sind.

Beantwortet am 09/12/2008 um 21:57
quelle vom benutzer

stimmen
29

Auf eine innere Verknüpfung, dann meinen sie das Gleiche. Allerdings werden Sie unterschiedliche Ergebnisse in einem äußeren bekommen join je nachdem , ob Sie die Join - Bedingung in der WHERE vs der ON - Klausel setzen. Schauen Sie sich auf diese Frage im Zusammenhang und diese Antwort (von mir).

Ich denke, es am meisten Sinn macht in der Gewohnheit zu sein, immer die Join-Bedingung in der ON-Klausel setzen (es sei denn es eine äußere Join und Sie wollen es tatsächlich in der where-Klausel), wie es deutlicher zu jeder macht Ihre Abfrage lesen welche Bedingungen die Tabellen verknüpft auf werden, und es hilft auch aus der WHERE-Klausel zu verhindern Dutzende von Zeilen lang sein.

Beantwortet am 09/12/2008 um 21:20
quelle vom benutzer

stimmen
12

Dieser Artikel eindeutig erklärt den Unterschied. Es erklärt auch die "ON joined_condition vs WHERE joined_condition oder joined_alias ist null".

Die WHERE-Klausel Filter sowohl die linke und die rechte Seite des Joins, während die ON-Klausel wird immer die rechte Seite filtern, dass nur.

  1. Wenn Sie wollen immer die linke Seite Reihen holen und nur beitreten, wenn eine bestimmte Bedingung übereinstimmt, dann sollten Sie die Klausel ON.
  2. Wenn Sie das Produkt zum Verbinden beiden Seiten filtern mögen, dann sollten Sie die WHERE-Klausel verwenden.
Beantwortet am 25/05/2014 um 15:20
quelle vom benutzer

stimmen
7

In Bezug auf den Optimierer, sollte es keinen Unterschied machen, ob Sie Ihre Klauseln mit ON beitreten definieren oder WHERE.

Aber meiner Meinung nach, ich denke, es ist viel klarer die ON-Klausel zu verwenden, wenn Joins benötigt. So können Sie einen bestimmten Abschnitt haben Sie Abfrage, die bestimmt, wie sich die Verbindung im Vergleich mit dem Rest der WHERE-Klauseln vermischte behandelt.

Beantwortet am 09/12/2008 um 21:21
quelle vom benutzer

stimmen
5

Es gibt große Unterschiede zwischen where - Klausel gegen on - Klausel , wenn sie kommen nach links kommt.

Hier ist Beispiel:

mysql> desc t1; 
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| fid   | int(11)     | NO   |     | NULL    |       |
| v     | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

Es fid ist id von Tabelle T2.

mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| v     | varchar(10) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

Abfrage auf "on-Klausel":

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K' 
    -> ;
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  1 |   1 | H | NULL | NULL |
|  2 |   1 | B | NULL | NULL |
|  3 |   2 | H | NULL | NULL |
|  4 |   7 | K | NULL | NULL |
|  5 |   5 | L | NULL | NULL |
+----+-----+---+------+------+
5 rows in set (0.00 sec)

Abfrage auf „Where-Klausel“:

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  4 |   7 | K | NULL | NULL |
+----+-----+---+------+------+
1 row in set (0.00 sec)

Es ist klar, dass die erste Abfrage einen Datensatz aus t1 und seine abhängige Zeile von T2 zurückgibt, falls vorhanden, für Zeile t1.v = ‚K‘.

Die zweite Abfrage gibt Zeilen aus t1, aber nur für t1.v = ‚K‘ wird damit die damit verbundene Reihe hat.

Beantwortet am 13/03/2016 um 06:31
quelle vom benutzer

stimmen
1

Normalerweise wird Filterung in der WHERE-Klausel verarbeitet, sobald die beiden Tabellen sind bereits verbunden worden. Es ist möglich, obwohl das Sie vielleicht eine oder beide der Tabellen filtern, bevor sie beitreten. dh gilt die where-Klausel auf die gesamte Ergebnismenge während der on-Klausel nur in Frage zu kommen gilt.

Beantwortet am 16/02/2018 um 05:29
quelle vom benutzer

stimmen
1

für eine bessere Leistung Tabellen sollten für reiht sich in eine spezielle indizierte Spalte zu verwenden.

so, wenn die Spalte auf Sie bedingen nicht einer dieser indizierten Spalten ist dann vermute ich, es ist besser, es zu halten in WO.

so dass Sie JOIN die indizierten Spalten verwenden, dann nach JOIN Sie die Bedingung auf der keine indizierten Spalte laufen.

Beantwortet am 12/12/2014 um 21:10
quelle vom benutzer

stimmen
0

Für eine innere Verknüpfung, WHEREund ONkönnen untereinander ausgetauscht werden. In der Tat ist es möglich , die Verwendung ONin einer korrelierten Unterabfrage. Beispielsweise:

update mytable
set myscore=100
where exists (
select 1 from table1
inner join table2
on (table2.key = mytable.key)
inner join table3
on (table3.key = table2.key and table3.key = table1.key)
...
)

Dies ist (IMHO) äußerst verwirrend an einem Menschen, und es ist sehr einfach zu verbinden , zu vergessen table1, etwas (weil die „Fahrer“ Tabelle , die einen „auf“ -Klausel nicht hat), aber es ist legal.

Beantwortet am 16/05/2014 um 23:40
quelle vom benutzer

stimmen
0

In SQL, die ‚WHERE‘ und ‚ON‘ -Klausel, sind so eine Art Conditional Statemants, aber der große Unterschied zwischen ihnen, die ‚Wo‘ -Klausel in Select / Update-Anweisungen verwendet wird, um die Bedingungen festgelegt, während der ‚ON‘ Klausel wenn die Datensätze in den Ziel- und Quellentabellen werden Matched verwendet wird, in Joins, wo er oder Schecks überprüft, bevor die Tabellen verknüpft sind

Zum Beispiel: - 'WHERE'

SELECT * FROM Mitarbeiter WHERE employee_id = 101

Zum Beispiel: - 'ON'

* Es gibt zwei Tabellen Mitarbeiter und employee_details werden die passenden Spalten employee_id. *

SELECT * FROM Mitarbeiter INNER JOIN employee_details ON employee.employee_id = employee_details.employee_id

Hoffe, ich habe Ihre Question.Revert zurück zur Klärung beantwortet.

Beantwortet am 05/02/2014 um 11:57
quelle vom benutzer

stimmen
0

Ich denke, es ist der Join-Sequenz-Effekt. In der oberen linken Fall beitreten, verbinden SQL Sie links und dann in dem Filter tun. Im Downer Fall finden Orders.ID = 12345 zuerst, und dann trete.

Beantwortet am 07/01/2014 um 04:49
quelle vom benutzer

stimmen
-5

dies ist meine Lösung.

SELECT song_ID,songs.fullname, singers.fullname
FROM music JOIN songs ON songs.ID = music.song_ID  
JOIN singers ON singers.ID = music.singer_ID
GROUP BY songs.fullname

Sie müssen die GROUP BYes an die Arbeit.

Ich hoffe das hilft.

Beantwortet am 26/04/2010 um 08:53
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more