MySQLでは、とJOIN
の違いは何ですか?私の知る限り、構文はもっと便利ですが、列名が同じでない場合はもう少し柔軟性があります。ただし、その違いはごくわずかであるため、。を廃止するだけだと思います。ON
USING()
USING()
ON
USING()
これには、目に見える以上のものがありますか?はいの場合、特定の状況でどちらを使用する必要がありますか?
これは主に糖衣構文ですが、いくつかの違いが注目に値します。
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
修飾に注意してください。それはあいまいさをもたらすので、SELECT
単に言うことは無効です:film_id
エラー1052(23000):フィールドリストの列'film_id'があいまいです
についてselect *
は、結合列は結果セットに2回表示されますが、: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>
ON
私がよりも有用であることがわかったとき、私はここでチップを入れるだろうと思ったUSING
。OUTER
結合がクエリに導入されるときです。
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)
;
ウィキペディアには、次の情報があります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からの残りの列を生成します。 。
USING句とON句がどのように機能するかを示すために、テーブルの主キー列を参照するテーブルの外部キー列を介して1対多のテーブル関係を形成する次post
のpost_comment
データベーステーブルがあると仮定します。post_id
post_comment
post_id
post
親post
テーブルには3つの行があります。
| post_id | title |
|---------|-----------|
| 1 | Java |
| 2 | Hibernate |
| 3 | JPA |
post_comment
子テーブルには3つのレコードがあります。
| post_comment_id | review | post_id |
|-----------------|-----------|---------|
| 1 | Good | 1 |
| 2 | Excellent | 1 |
| 3 | Awesome | 2 |
従来、INNER JOIN
またはLEFT JOIN
クエリを作成するときは、ON句を使用して結合条件を定義していました。
たとえば、コメントとそれに関連する投稿のタイトルおよび識別子を取得するには、次のSQLプロジェクションクエリを使用できます。
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
そして、次の結果セットが返されます。
| post_id | title | review |
|---------|-----------|-----------|
| 1 | Java | Good |
| 1 | Java | Excellent |
| 2 | Hibernate | Awesome |
外部キー列とそれが参照する列の名前が同じである場合、次の例のようにUSING句を使用できます。
SELECT
post_id,
title,
review
FROM post
INNER JOIN post_comment USING(post_id)
ORDER BY post_id, post_comment_id
また、この特定のクエリの結果セットは、ON句を使用した以前のSQLクエリと同じです。
| post_id | title | review |
|---------|-----------|-----------|
| 1 | Java | Good |
| 1 | Java | Excellent |
| 2 | Hibernate | Awesome |
USING句は、Oracle、PostgreSQL、MySQL、およびMariaDBで機能します。SQL ServerはUSING句をサポートしていないため、代わりにON句を使用する必要があります。
USING句は、INNER、LEFT、RIGHT、およびFULLJOINステートメントで使用できます。
SELECT *
ここで、前のON句のクエリを変更して、次を使用してすべての列を選択するとしますSELECT *
。
SELECT *
FROM post
INNER JOIN post_comment ON post.post_id = post_comment.post_id
ORDER BY post.post_id, post_comment_id
次の結果セットを取得します。
| post_id | title | post_comment_id | review | post_id |
|---------|-----------|-----------------|-----------|---------|
| 1 | Java | 1 | Good | 1 |
| 1 | Java | 2 | Excellent | 1 |
| 2 | Hibernate | 3 | Awesome | 2 |
ご覧のとおり、とテーブルの両方に列が含まれているため、
post_id
が重複しています。post
post_comment
post_id
SELECT *
一方、SELECT *
JOIN条件のUSING句を特徴とするクエリを実行すると、次のようになります。
SELECT *
FROM post
INNER JOIN post_comment USING(post_id)
ORDER BY post_id, post_comment_id
次の結果セットが得られます。
| post_id | title | post_comment_id | review |
|---------|-----------|-----------------|-----------|
| 1 | Java | 1 | Good |
| 1 | Java | 2 | Excellent |
| 2 | Hibernate | 3 | Awesome |
今回は
post_id
列が重複排除post_id
されているため、結果セットに1つの列が含まれていることがわかります。
外部キー列名が参照する列と一致するようにデータベーススキーマが設計されており、JOIN条件が外部キー列の値が他のテーブルのミラーリング列の値と等しいかどうかのみをチェックする場合は、USINGを使用できます。句。
それ以外の場合、外部キー列名が参照列と異なる場合、またはより複雑な結合条件を含めたい場合は、代わりにON句を使用する必要があります。
phpMyAdminでこれを実験している人のために、一言:
phpMyAdminにはいくつかの問題があるようUSING
です。記録として、これはLinux Mintで実行されるphpMyAdmin、バージョン: "4.5.4.1deb2ubuntu2"、データベースサーバー: "10.2.14-MariaDB-10.2.14 + maria〜xenial--mariadb.orgバイナリディストリビューション"です。
SELECT
phpMyAdminとターミナル(コマンドライン)の両方でコマンドをJOIN
実行しUSING
ましたが、phpMyAdminのコマンドは不可解な応答を生成します。
1)LIMIT
最後の句は無視されているように見えます。
2)結果とともにページの上部に報告された想定行数が間違っている場合があります。たとえば、4が返されますが、上部に「行0〜24を表示しています(合計2503、クエリに0.0018秒かかりました)」と表示されます。 「」
通常どおりmysqlにログオンし、同じクエリを実行しても、これらのエラーは発生しません。を使用してphpMyAdminで同じクエリを実行しても、これらのエラーは発生しませんJOIN ... ON ...
。おそらくphpMyAdminのバグです。