it-swarm.com.de

MySQL ON vs USING?

Was ist der Unterschied zwischen JOIN und USING() in einem MySQL ON? Soweit ich das beurteilen kann, ist USING() nur eine bequemere Syntax, während ON etwas mehr Flexibilität bietet, wenn die Spaltennamen nicht identisch sind. Dieser Unterschied ist jedoch so gering, dass man meinen würde, sie würden USING() einfach wegschaffen.

Gibt es mehr, als man denkt? Wenn ja, welche sollte ich in einer bestimmten Situation verwenden?

232
Nathanael

Es ist hauptsächlich syntaktischer Zucker, aber ein paar Unterschiede sind bemerkenswert:

AUF ist der allgemeinere der beiden. Man kann Tabellen auf einer Spalte, einer Menge von Spalten und sogar einer Bedingung verbinden. Zum Beispiel:

SELECT * FROM world.City JOIN world.Country ON (City.CountryCode = Country.Code) WHERE ...

MIT ist nützlich, wenn beide Tabellen eine Spalte mit genau demselben Namen gemeinsam haben, für die sie verknüpft sind. In diesem Fall kann man sagen:

SELECT ... FROM film JOIN film_actor USING (film_id) WHERE ...

Ein zusätzlicher Vorteil von Nice ist, dass man die Joining-Spalten nicht vollständig qualifizieren muss:

SELECT film.title, film_id -- film_id is not prefixed
FROM film
JOIN film_actor USING (film_id)
WHERE ...

Um dies zu veranschaulichen und mit AUF zu tun, müssten wir schreiben:

SELECT film.title, film.film_id -- film.film_id is required here
FROM film
JOIN film_actor ON (film.film_id = film_actor.film_id)
WHERE ...

Beachten Sie die film.film_id - Qualifikation in der SELECT -Klausel. Es wäre ungültig, nur film_id Zu sagen, da dies zu einer Mehrdeutigkeit führen würde:

FEHLER 1052 (23000): Die Spalte 'film_id' in der Feldliste ist nicht eindeutig

Wie bei select * erscheint die Verknüpfungsspalte in der Ergebnismenge zweimal mit ON, während sie nur einmal mit USING erscheint:

mysql> create table t(i int);insert t select 1;create table t2 select*from t;
Query OK, 0 rows affected (0.11 sec)

Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

Query OK, 1 row affected (0.19 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select*from t join t2 on t.i=t2.i;
+------+------+
| i    | i    |
+------+------+
|    1 |    1 |
+------+------+
1 row in set (0.00 sec)

mysql> select*from t join t2 using(i);
+------+
| i    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql>
363
Shlomi Noach

Ich dachte, ich würde hier mit einsteigen, wenn ich festgestellt habe, dass ON nützlicher ist als USING. Dies ist der Fall, wenn OUTER - Joins in Abfragen eingefügt werden.

ON profitiert davon, dass die Ergebnismenge der Tabelle, zu der eine Abfrage OUTER beitritt, eingeschränkt werden kann, während die Verknüpfung OUTER beibehalten wird. Wenn Sie versuchen, die Ergebnismenge durch Angabe einer WHERE - Klausel einzuschränken, wird der Join OUTER in einen Join INNER geändert.

Zugegeben, dies kann ein relativer Eckfall sein. Es lohnt sich aber da draußen zu sein .....

Zum Beispiel:

CREATE TABLE country (
   countryId int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
   country varchar(50) not null,
  UNIQUE KEY countryUIdx1 (country)
) ENGINE=InnoDB;

insert into country(country) values ("France");
insert into country(country) values ("China");
insert into country(country) values ("USA");
insert into country(country) values ("Italy");
insert into country(country) values ("UK");
insert into country(country) values ("Monaco");


CREATE TABLE city (
  cityId int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
  countryId int(10) unsigned not null,
  city varchar(50) not null,
  hasAirport boolean not null default true,
  UNIQUE KEY cityUIdx1 (countryId,city),
  CONSTRAINT city_country_fk1 FOREIGN KEY (countryId) REFERENCES country (countryId)
) ENGINE=InnoDB;


insert into city (countryId,city,hasAirport) values (1,"Paris",true);
insert into city (countryId,city,hasAirport) values (2,"Bejing",true);
insert into city (countryId,city,hasAirport) values (3,"New York",true);
insert into city (countryId,city,hasAirport) values (4,"Napoli",true);
insert into city (countryId,city,hasAirport) values (5,"Manchester",true);
insert into city (countryId,city,hasAirport) values (5,"Birmingham",false);
insert into city (countryId,city,hasAirport) values (3,"Cincinatti",false);
insert into city (countryId,city,hasAirport) values (6,"Monaco",false);

-- Gah. Left outer join is now effectively an inner join 
-- because of the where predicate
select *
from country left join city using (countryId)
where hasAirport
; 

-- Hooray! I can see Monaco again thanks to 
-- moving my predicate into the ON
select *
from country co left join city ci on (co.countryId=ci.countryId and ci.hasAirport)
; 
15
Tom Mac

Wikipedia enthält die folgenden Informationen zu USING:

Das USING-Konstrukt ist jedoch mehr als nur syntaktischer Zucker, da sich die Ergebnismenge von der Ergebnismenge der Version mit dem expliziten Prädikat unterscheidet. Insbesondere werden alle in der USING-Liste genannten Spalten nur einmal mit einem nicht qualifizierten Namen und nicht einmal für jede Tabelle im Join angezeigt. Im obigen Fall gibt es eine einzelne Spalte "DepartmentID" und keine "employee.DepartmentID" oder "department.DepartmentID".

Tabellen, über die es gesprochen hat:

enter image description here

Die Postgres Dokumentation definiert sie auch ziemlich gut:

Die ON-Klausel ist die allgemeinste Art von Join-Bedingung: Sie verwendet einen Booleschen Wertausdruck der gleichen Art, wie er in einer WHERE-Klausel verwendet wird. Ein Zeilenpaar aus T1 und T2 stimmt überein, wenn der Ausdruck ON den Wert true hat.

Die USING-Klausel ist eine Kurzform, mit der Sie die spezielle Situation nutzen können, in der beide Seiten des Joins denselben Namen für die Join-Spalte (n) verwenden. Es verwendet eine durch Kommas getrennte Liste der gemeinsam genutzten Spaltennamen und bildet eine Verknüpfungsbedingung, die jeweils einen Gleichheitsvergleich enthält. Wenn Sie beispielsweise T1 und T2 mit USING (a, b) verbinden, wird die Verknüpfungsbedingung ON T1.a = T2.a AND T1.b = T2.b erzeugt.

Darüber hinaus unterdrückt die Ausgabe von JOIN USING redundante Spalten: Es ist nicht erforderlich, beide übereinstimmenden Spalten zu drucken, da sie gleiche Werte haben müssen. Während JOIN ON alle Spalten von T1 gefolgt von allen Spalten von T2 erzeugt, erzeugt JOIN USING eine Ausgabespalte für jedes der aufgelisteten Spaltenpaare (in der aufgelisteten Reihenfolge), gefolgt von allen verbleibenden Spalten von T1, gefolgt von allen verbleibenden Spalten von T2 .

9
Robert Rocha

Für diejenigen, die damit in phpMyAdmin experimentieren, nur ein Wort:

phpMyAdmin scheint ein paar Probleme mit USING zu haben. Für die Aufzeichnung ist dies phpMyAdmin unter Linux Mint, Version: "4.5.4.1deb2ubuntu2", Datenbankserver: "10.2.14-MariaDB-10.2.14 + maria ~ xenial - mariadb.org binary distribution".

Ich habe SELECT Befehle mit JOIN und USING sowohl in phpMyAdmin als auch in Terminal (Befehlszeile) ausgeführt, und die Befehle in phpMyAdmin haben einige verblüffende Antworten hervorgerufen:

1) Eine LIMIT -Klausel am Ende scheint ignoriert zu werden.
2) Die angebliche Anzahl der Zeilen, die oben auf der Seite mit den Ergebnissen angegeben wurden, ist manchmal falsch: Beispiel: 4 werden zurückgegeben, aber oben steht "Zeilen 0 - 24 werden angezeigt (insgesamt 2503, Abfrage dauerte 0,0018 Sekunden.) "

Wenn Sie sich normal bei mysql anmelden und dieselben Abfragen ausführen, treten diese Fehler nicht auf. Diese Fehler treten auch nicht auf, wenn dieselbe Abfrage in phpMyAdmin mit JOIN ... ON ... Ausgeführt wird. Vermutlich ein phpMyAdmin-Fehler.

0
mike rodent