360 Stimmen

MySQL JOIN ON vs. USING?

In einem MySQL JOIN Was ist der Unterschied zwischen ON y USING() ? Soweit ich das beurteilen kann, USING() ist einfach die bequemere Syntax, während ON erlaubt ein wenig mehr Flexibilität, wenn die Spaltennamen nicht identisch sind. Dieser Unterschied ist jedoch so gering, dass man meinen könnte, sie würden einfach die USING() .

Steckt mehr dahinter, als man auf den ersten Blick sieht? Wenn ja, welche sollte ich in einer bestimmten Situation verwenden?

575voto

Shlomi Noach Punkte 8463

Es handelt sich größtenteils um syntaktischen Zucker, aber ein paar Unterschiede sind bemerkenswert:

ON ist die allgemeinere der beiden. Man kann Tabellen über eine Spalte, eine Gruppe von Spalten und sogar eine Bedingung verbinden. Zum Beispiel:

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

VERWENDUNG ist nützlich, wenn beide Tabellen eine Spalte mit genau demselben Namen haben, über die sie sich verbinden. In diesem Fall kann man sagen:

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

Ein weiterer Vorteil ist, dass man die Verbindungsspalten nicht vollständig qualifizieren muss:

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

Zur Veranschaulichung, um die oben genannten Aufgaben mit ON 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, einfach zu sagen film_id da dies zu einer Mehrdeutigkeit führen würde:

FEHLER 1052 (23000): Spalte 'film_id' in Feldliste ist mehrdeutig

In Bezug auf *`select ** erscheint die verbindende Spalte zweimal in der Ergebnismenge mitONwährend es nur einmal beiUSING` :

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>

27voto

Tom Mac Punkte 9525

Ich dachte, ich würde hier mitschreiben, wenn ich etwas gefunden habe. ON nützlicher zu sein als USING . Es ist, wenn OUTER Joins in Abfragen eingeführt werden.

ON profitiert von der Möglichkeit, die Ergebnismenge der Tabelle, die eine Abfrage OUTER zu beschränken und gleichzeitig die OUTER verbinden. Der Versuch, die Ergebnismenge durch Angabe einer WHERE Klausel wird effektiv die OUTER zu einer INNER verbinden.

Zugegeben, das mag ein relativer Einzelfall sein. Aber es lohnt sich, es zu erwähnen: .....

F

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)
;

26voto

Robert Rocha Punkte 9410

ウィキペディア hat die folgenden Informationen über USING :

Das USING-Konstrukt ist jedoch mehr als nur ein syntaktischer Zucker, da die Ergebnismenge unterscheidet sich von der Ergebnismenge der Version mit der expliziten Prädikat. Konkret bedeutet dies, dass jede Spalte Liste erwähnten Spalten erscheinen nur einmal, mit einem unqualifizierten Namen, anstatt einmal für jede Tabelle in der Verknüpfung. Im obigen Fall gibt es eine einzige DepartmentID Spalte und keine employee.DepartmentID oder Abteilung.AbteilungsID.

Tische, über die sie gesprochen hat:

enter image description here

のことです。 Postgres Die Dokumentation definiert sie auch ziemlich gut:

Die ON-Klausel ist die allgemeinste Art der Verknüpfungsbedingung: booleschen Wertausdruck der gleichen Art, wie er in einer WHERE Klausel verwendet wird. Ein Paar von Zeilen aus T1 und T2 stimmt überein, wenn der ON-Ausdruck zu wahr ausgewertet wird.

Die USING-Klausel ist eine Abkürzung, mit der y die besondere Situation, in der beide Seiten der Verknüpfung denselben Namen verwenden für die verbindende(n) Spalte(n) verwenden. Sie nimmt eine kommagetrennte Liste der gemeinsamen Spaltennamen und bildet eine Verknüpfungsbedingung, die einen Gleichheitsvergleich für jede Spalte enthält. Zum Beispiel, die Verknüpfung von T1 und T2 mit USING (a, b) ergibt die Join-Bedingung ON T1.a = T2.a AND T1.b = T2.b.

Außerdem wird die Ausgabe von JOIN USING suppre Es besteht keine Notwendigkeit, die beiden übereinstimmenden Spalten zu drucken, da sie gleiche Werte haben. Während JOIN ON alle Spalten von T1 ausgibt, gefolgt von alle Spalten von T2 ausgibt, erzeugt JOIN USING eine Ausgabespalte für jede eine Ausgabespalte für jedes der aufgeführten Spaltenpaare (in der aufgeführten Reihenfolge), gefolgt von allen verbleibenden Spalten aus T1, gefolgt von allen verbleibenden Spalten aus T2.

13voto

Vlad Mihalcea Punkte 121171

Datenbank-Tabellen

Um zu demonstrieren, wie die USING- und ON-Klauseln funktionieren, nehmen wir an, dass wir Folgendes haben post y post_comment Datenbanktabellen, die eine eins-zu-viele-Tabellenbeziehung über die post_id Fremdschlüsselspalte in der post_comment Tabelle mit Verweis auf die post_id Primärschlüsselspalte in der post Tisch:

SQL USING vs ON clauses table relationship

Der Elternteil post Tabelle hat 3 Zeilen:

| post_id | title     |
|---------|-----------|
| 1       | Java      |
| 2       | Hibernate |
| 3       | JPA       |

und die post_comment Die untergeordnete Tabelle enthält die 3 Datensätze:

| post_comment_id | review    | post_id |
|-----------------|-----------|---------|
| 1               | Good      | 1       |
| 2               | Excellent | 1       |
| 3               | Awesome   | 2       |

Die JOIN ON-Klausel unter Verwendung einer benutzerdefinierten Projektion

Traditionell wird beim Schreiben einer INNER JOIN ou LEFT JOIN Abfrage verwenden wir zufällig die ON-Klausel, um die Join-Bedingung zu definieren.

Um beispielsweise die Kommentare zusammen mit dem zugehörigen Beitragstitel und -bezeichner zu erhalten, können wir die folgende SQL-Projektionsabfrage verwenden:

SELECT
   post.post_id,
   title,
   review
FROM post
INNER JOIN post_comment ON post.post_id = post_comment.post_id
ORDER BY post.post_id, post_comment_id

Und wir erhalten die folgende Ergebnismenge zurück:

| post_id | title     | review    |
|---------|-----------|-----------|
| 1       | Java      | Good      |
| 1       | Java      | Excellent |
| 2       | Hibernate | Awesome   |

Die JOIN USING-Klausel unter Verwendung einer benutzerdefinierten Projektion

Wenn die Fremdschlüsselspalte und die Spalte, auf die sie verweist, denselben Namen haben, können wir die USING-Klausel verwenden, wie im folgenden Beispiel:

SELECT
  post_id,
  title,
  review
FROM post
INNER JOIN post_comment USING(post_id)
ORDER BY post_id, post_comment_id

Und die Ergebnismenge für diese spezielle Abfrage ist identisch mit der vorherigen SQL-Abfrage, die die ON-Klausel verwendet hat:

| post_id | title     | review    |
|---------|-----------|-----------|
| 1       | Java      | Good      |
| 1       | Java      | Excellent |
| 2       | Hibernate | Awesome   |

Die USING-Klausel funktioniert für Oracle, PostgreSQL, MySQL und MariaDB. SQL Server unterstützt die USING-Klausel nicht, so dass Sie stattdessen die ON-Klausel verwenden müssen.

Die USING-Klausel kann mit INNER-, LEFT-, RIGHT- und FULL JOIN-Anweisungen verwendet werden.

SQL JOIN ON-Klausel mit SELECT *

Wenn wir nun die vorherige ON-Klausel-Abfrage ändern, um alle Spalten auszuwählen, indem wir SELECT * :

SELECT *
FROM post
INNER JOIN post_comment ON post.post_id = post_comment.post_id
ORDER BY post.post_id, post_comment_id

Wir werden die folgende Ergebnismenge erhalten:

| post_id | title     | post_comment_id | review    | post_id |
|---------|-----------|-----------------|-----------|---------|
| 1       | Java      | 1               | Good      | 1       |
| 1       | Java      | 2               | Excellent | 1       |
| 2       | Hibernate | 3               | Awesome   | 2       |

Wie Sie sehen können, ist die post_id es vervielfältigt weil sowohl die post y post_comment Tabellen enthalten eine post_id Spalte.

SQL JOIN USING-Klausel mit SELECT *

Andererseits, wenn wir eine SELECT * Abfrage, die die USING-Klausel für die JOIN-Bedingung enthält:

SELECT *
FROM post
INNER JOIN post_comment USING(post_id)
ORDER BY post_id, post_comment_id

Wir erhalten die folgende Ergebnismenge:

| post_id | title     | post_comment_id | review    |
|---------|-----------|-----------------|-----------|
| 1       | Java      | 1               | Good      |
| 1       | Java      | 2               | Excellent |
| 2       | Hibernate | 3               | Awesome   |

Sie können sehen, dass dieses Mal die post_id Spalte wird dedupliziert, so dass es eine einzige post_id Spalte, die in der Ergebnismenge enthalten ist.

Schlussfolgerung

Wenn das Datenbankschema so gestaltet ist, dass die Namen der Fremdschlüsselspalten mit den Spalten übereinstimmen, auf die sie verweisen, und die JOIN-Bedingungen nur prüfen, ob der Wert der Fremdschlüsselspalte gleich dem Wert der Spiegelungsspalte in der anderen Tabelle ist, dann können Sie die USING-Klausel verwenden.

Wenn sich der Name der Fremdschlüsselspalte von der referenzierenden Spalte unterscheidet oder Sie eine komplexere Join-Bedingung einfügen möchten, sollten Sie stattdessen die ON-Klausel verwenden.

3voto

mike rodent Punkte 12041

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

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

Ich habe gelaufen SELECT Befehle mit JOIN y USING sowohl in phpMyAdmin als auch in Terminal (Kommandozeile), und die in phpMyAdmin liefern einige verwirrende Antworten:

1) a LIMIT Klausel am Ende scheint ignoriert zu werden.
2) Die vermeintliche Anzahl der Zeilen, die oben auf der Seite mit den Ergebnissen angezeigt wird, ist manchmal falsch: Es werden z. B. 4 Zeilen zurückgegeben, aber oben heißt es: "Zeigt Zeilen 0 - 24 (2503 insgesamt, Abfrage dauerte 0,0018 Sekunden.)"

Wenn Sie sich normal bei mysql anmelden und die gleichen Abfragen ausführen, treten diese Fehler nicht auf. Die Fehler treten auch nicht auf, wenn Sie die gleiche Abfrage in phpMyAdmin mit JOIN ... ON ... . Vermutlich ein phpMyAdmin-Fehler.

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