MySQL ON vs USING?


252

MySQLではJOIN、違いは何であるONとはUSING()?私が知る限りでUSING()は、構文はより便利ONですが、列名が同一でない場合は少し柔軟性があります。ただし、その違いはごくわずかなので、彼らはを排除するだけだと思いますUSING()

目に見える以上のものはありますか?はいの場合、特定の状況でどちらを使用すればよいですか?


1
NATURAL JOINをもあります:stackoverflow.com/questions/8696383/...
allyourcode

using結合の他に別の使い方があることに注意してください。stackoverflow.com/a/13750399/632951を
Pacerier

回答:


400

それは主に構文上の砂糖ですが、いくつかの違いが注目に値します:

ONは2つのうちより一般的です。列、列のセット、さらには条件でテーブルを結合できます。例えば:

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

USINGは、両方のテーブルが結合するまったく同じ名前の列を共有している場合に役立ちます。この場合、次のように言うことができます。

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

追加の優れた点は、結合する列を完全に修飾する必要がないことです。

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

例として、ONで上記を行うには、次のように記述する必要があります。

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 ...

条項のfilm.film_id条件に注意してくださいSELECTfilm_idあいまいになる可能性があるため、次のように言うだけでは無効です。

エラー1052(23000):フィールドリストの列 'film_id'があいまいです

select *結合列は、で二回、結果セットに表示されON、それは1回だけ表示されている間USING

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>

2
+1構文の違いに関する良い答え。もしあれば、パフォーマンスの違いに興味があります。にUSING解釈すると思いONます。
Jason McCreary

9
実際、どちらもプレーンな古いシータスタイルに解釈されます。これは、クエリでEXPLAIN EXTENDEDを呼び出し、その後にSHOW WARNINGSを呼び出すことで確認できます。
Shlomi Noach

2
また、複合主キーで結合するときに役立つUSING(カテゴリ,field_id )を実行することもできます。また、オプティマイザがパフォーマンスを改善するために使用する場合があることも聞きましUSING
Timo Huovinen

あるUSINGMySQLの定義やそれが標準ですか?
PhoneixS


18

ONよりも便利であることがわかったとき、私はここにチップを入れると思いましたUSINGOUTER結合がクエリに導入されるときです。

ONクエリをOUTER結合しているテーブルの結果セットを、OUTER結合を維持しながら制限できるようにすることの利点。WHERE句を指定して結果セットを制限しようとすると、事実上、OUTER結合が結合に変わりINNERます。

これは相対的なコーナーケースである可能性があります。でもそこに出す価値は.....

例えば:

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

4
非常に良い点。using提供されるすべての利点のうち、他の述語と組み合わせることはできませんselect*from t join t2 using(i) and on 1
Pacerier

where hasAirport ;- これは何を意味するのでしょうか ?と比較する値はありません。
Istiaque Ahmed

また、ONを使用すると、単なる=よりもはるかに多くの比較を実行できることに注意してください。Like SELECT * FROM country LEFT JOIN city ON country.countryId=city.countryId AND city.city BETWEEN 'C' AND 'E' はすべての国をリストしますが、CまたはD(存在する場合)で始まる都市のみをリストします。(「E」と呼ばれる町)
Roemer

ONでサブクエリを使用してJOINを実行したこともあります!!! それはすべて可能であり、時には非常に効果的です。
Roemer

11

ウィキペディアには、次の情報がありますUSING

ただし、結果セットは明示的な述語を持つバージョンの結果セットとは異なるため、USING構文は単なる構文上の糖衣以上のものです。具体的には、USINGリストで言及されている列は、結合内の各テーブルに対して1回ではなく、非修飾名で1回だけ表示されます。上記の場合、DepartmentID列は1つで、employee.DepartmentIDやdepartment.DepartmentIDはありません。

それが話していたテーブル:

ここに画像の説明を入力してください

Postgresのドキュメントもかなりよく、それらを定義しています。

ON句は、最も一般的な種類の結合条件です。これは、WHERE句で使用されるのと同じ種類のブール値式を取ります。ON式がtrueと評価された場合、T1とT2の行のペアが一致します。

USING句は、結合の両側で結合列に同じ名前を使用する特定の状況を利用できるようにするための省略形です。これは、共有列名のコンマ区切りリストを取り、それぞれの等価比較を含む結合条件を形成します。たとえば、T1とT2をUSING(a、b)で結合すると、結合条件ON T1.a = T2.a AND T1.b = T2.bが生成されます。

さらに、JOIN USINGの出力は冗長な列を抑制します。一致する列は両方とも同じ値でなければならないため、一致する両方の列を出力する必要はありません。JOIN ONはT1のすべての列に続いてT2のすべての列を生成しますが、JOIN USINGはリストされた列のペアごとに(リストされた順序で)1つの出力列を生成し、T1の残りの列が続き、T2の残りの列が続きます。 。


1

phpMyAdminでこれを試す人のために、一言だけ:

phpMyAdminには、いくつかの問題があるようUSINGです。記録のために、これはLinux Mintで実行されるphpMyAdmin、バージョン:「4.5.4.1deb2ubuntu2」、データベースサーバー:「10.2.14-MariaDB-10.2.14 + maria〜xenial-mariadb.orgバイナリディストリビューション」です。

私が実行しているSELECT使用してコマンドをJOINし、USING両方のphpMyAdminにとターミナル(コマンドライン)で、そしてphpMyAdminの中のものは、いくつかの不可解な応答を生成します。

1)LIMIT末尾の句が無視されているようです。
2)結果としてページの上部に報告されると想定される行数が間違っていることがあります。たとえば、4が返されますが、上部には「行0〜24を表示しています(合計2503、クエリには0.0018秒かかりました)。 」

mysqlに正常にログオンして同じクエリを実行しても、これらのエラーは発生しません。また、phpMyAdminで同じクエリを実行しても、これらのエラーは発生しませんJOIN ... ON ...。おそらくphpMyAdminのバグです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.