目次
とある日
とある内容について検証しているときに気づいたSQLのUSINGとONの違いについて調べるとあまり解説されていなかったので各句の違いとなぜ気づかなかったかについての記録を残そうと思います。
環境
項目 | 詳細 |
---|---|
DataBase | MySQL 8.0.23 |
OS | CentOS8 |
さらなる詳細は下記のテスト環境の記事を参照してください。
USINGとONの違いについて
一般的に一番知られているであろう違いと自分が知らなかった違いの2つを解説しようと思います。
1. 同一列名
一番知られている違いとしては、USINGは結合するテーブルに同一名の列が存在することだと思います。
その点、ONは柔軟に対応できるようになっています。
select * from join1 inner join join2 on join1.join1_id = join2.join1_id; select * from join1 inner join join2 using(join1_id);
2.結合後列数減少
自分が知らなかった違いはこれになります。
USINGで結合した場合は、結合に使用した2つの列は同一の列となり一つになります。
先程のSQLを実行した結果↓
select * from join1 inner join join2 using(join1_id); join1_id|name|join2_id| --------|----|--------| 1|aaa | 1| 1|aaa | 2| 2|bbb | 3| 3|ccc | 4|
反対に、ONの場合は結合に使用した列は2つとも残ります。
先程のSQLを実行した結果↓
select * from join1 inner join join2 on join1.join1_id = join2.join1_id; join1_id|name|join2_id|join1_id| --------|----|--------|--------| 1|aaa | 1| 1| 1|aaa | 2| 1| 2|bbb | 3| 2| 3|ccc | 4| 3|
USINGのSQL結果では、join1_id
が一つだけ存在しています。
一方、ONの方では2つあります。
結合に使用したそれぞれのテーブルに存在する列はそのまま存在しています。
列数減少による問題
この列数減少違いでどのような影響があるかというと、SELECT句などで結合列を指定するときに明示的にテーブル名を明記する必要があります。
Using
mysql> select join1_id from join1 inner join join2 using(join1_id); +----------+ | join1_id | +----------+ | 1 | | 1 | | 2 | | 3 | +----------+ 4 rows in set (0.01 sec)
On
mysql> select join1.join1_id from join1 inner join join2 on join1.join1_id = join2.join1_id; +----------+ | join1_id | +----------+ | 1 | | 1 | | 2 | | 3 | +----------+ 4 rows in set (0.00 sec)
ONはテーブル名を明記しないとエラーになります。
2つあるのですから当然どちらの列を参照しているかわからないので起きる現象ですね。
mysql> select join1_id from join1 inner join join2 on join1.join1_id = join2.jo in1_id; ERROR 1052 (23000): Column 'join1_id' in field list is ambiguous
ちなみに、Usingでテーブル名を指定してもエラーは発生しないし特に問題はない。
mysql> select join1.join1_id from join1 inner join join2 using(join1_id); +----------+ | join1_id | +----------+ | 1 | | 1 | | 2 | | 3 | +----------+ 4 rows in set (0.00 sec)
気づかなかった理由
気づかなかった理由として、考えたときに2つほど浮かんだので記録として残します。
Onの多用
先ほど説明したとおり、ONは結合列が同一名でなくても使用できるためあまりUSINGを使用しなかった。
SQLの書籍でも基本的には結合するテーブルのIDが同一ではない場合が多いので、結合する場合はONを使用した記述が多かったため自分も特に何も考えないでONを使用していた。
結合列の参照をしない
今回気づいたのは、別の検証中にSELECT句で”*”を使用してすべての列を出力しようとしたときに気づきました。
自分はずっと結合を使用したSQLの場合、結合列名の重複を気にしないように常にテーブル名をしていすることにしていました。
なので、結合列を意識して参照しないので気づかなかった。
〆
正直あまり気にしなくてもいい違いではありそうな気がするが、気づいたときは”へぇー、違うんだ”ってなったので記事にしました。
すごい初歩的な内容な気もしますが、SQLを勉強し始めて約三年ぐらいが立ちますが知らなかった違いでした。
類似した使用方法をするものに関しては、微妙な違いが存在しますね。
他にも、気づいていない違いがありそうな気がするのですが、もっと深くSQLやMySQLを勉強していかないといけないですね。