SQL の JOIN は省略できる — INNER/OUTER キーワードとカンマ結合の整理


JOIN とだけ書いたら INNER JOIN になるのか」「LEFT JOINLEFT OUTER JOIN は違うのか」という疑問への答えを先に書くと、どちらもまったく同じものです。INNEROUTER は書いても書かなくても意味の変わらないキーワードで、省略しても結果は 1 行も変わりません。

この記事では、省略形の対応表と「では実際どこまで省いて書くか」の指針、そして JOIN の省略とよく混同される「カンマ結合(FROM a, b)」がなぜ別物なのかを、実際に動かした結果つきで整理します。動作確認は 2026年7月に PostgreSQL 17.10 / MySQL 8.4.10 / SQLite 3.51.0 と Oracle Database Free(23ai系, 23.26.2.0.0)で行いました。JOIN そのものの種類と結果の違いは SQL の JOIN の種類と違いまとめ — INNER/LEFT/RIGHT/FULL/CROSS【2026年更新】 にまとめているので、そちらもどうぞ。

省略形の対応表

省略した書き方正式な(長い)書き方意味
JOININNER JOIN内部結合
LEFT JOINLEFT OUTER JOIN左外部結合
RIGHT JOINRIGHT OUTER JOIN右外部結合
FULL JOINFULL OUTER JOIN完全外部結合(対応 DB のみ。MySQL は非対応)

規則は単純で、INNEROUTER だけが省略可能です。PostgreSQL の公式マニュアルにも「INNER と OUTER はすべての形で省略可能。INNER がデフォルトで、LEFT・RIGHT・FULL は外部結合を意味する」と明記されています。逆に LEFTRIGHTFULL は結合の向きを決める本体なので省略できません。

これは SQL 標準の話なので特定の DB の方言ではありません。手元でも PostgreSQL 17 / MySQL 8.4 / SQLite 3.51 の 3 つで、表のどの組も省略の有無による結果の違いがないことを確認しました(FULL JOIN の行のみ、FULL 結合に対応しない MySQL を除く 2 つでの確認です。また Oracle Database Free でも JOIN = INNER JOIN の省略で同じ結果になることを確認しています)。

実際に確認する

次のサンプルで試します(コピペで動きます)。

CREATE TABLE emp (id INT, name VARCHAR(20), dept_id INT);
CREATE TABLE dept (dept_id INT, dept_name VARCHAR(20));
INSERT INTO emp VALUES (1,'佐藤',10),(2,'鈴木',20),(3,'高橋',NULL),(4,'田中',40);
INSERT INTO dept VALUES (10,'営業部'),(20,'開発部'),(30,'総務部');

JOININNER JOIN を並べて実行してみます。

SELECT * FROM emp JOIN dept USING(dept_id);
SELECT * FROM emp INNER JOIN dept USING(dept_id);

どちらも結果は同じ 2 行です(PostgreSQL 17 で実行。USING を使ったので結合列 dept_id は先頭に 1 回だけ現れます)。

dept_ididnamedept_name
101佐藤営業部
202鈴木開発部

LEFT JOINLEFT OUTER JOIN も同様に、どちらも同じ 4 行(dept 側に相手がいない高橋・田中は dept_name が NULL)になります。INNER と LEFT で結果がどう変わるかを詳しく見たい方は INNER JOIN と LEFT JOIN の違い — 結果がどう変わるか実例で確認 をどうぞ。

では省略して書くべきか

結果が同じなので、あとは読みやすさとチームの流儀の問題です。よく見かける組み合わせは「内部結合は JOIN だけ、外部結合は LEFT JOIN(OUTER は省略)」で、私もこの書き方です。INNER を省いても JOIN が内部結合なのは読み手に伝わりますし、外部結合は LEFT の文字さえあれば十分区別できるので、OUTER まで書くと少し冗長に感じます。

一方で「INNER は明示する」派もいて、こちらは JOIN が並ぶ長いクエリで内部結合と外部結合の区別を目立たせたいときには合理的です。どちらが正しいという話ではないので、既存のコードベースがあるならその流儀に合わせるのが一番です。

カンマ結合(FROM a, b)は「JOIN の省略形」ではない

「JOIN の省略」で検索すると、こういう書き方の話が混ざって出てくることがあります。

SELECT * FROM emp, dept WHERE emp.dept_id = dept.dept_id;

FROM にテーブルをカンマで並べ、結合条件を WHERE に書くスタイルです。結果は先ほどの INNER JOIN と同じ 2 行になりますが、これは JOIN キーワードの省略形ではなく、JOIN 構文が標準化される前からある旧スタイルの結合です。今から新しく書くクエリでは JOIN 構文をおすすめします。理由は 2 つあります。

JOIN と混在させるとエラーになる

カンマ結合と JOIN 句は結合の優先順位が違います。JOIN 句のほうが先に結合されるため、混ぜて書くと ON からカンマ側のテーブルが見えず、エラーになります。実際に試すとこうなります。

SELECT * FROM emp, dept JOIN emp e2 ON emp.dept_id = e2.dept_id;
  • PostgreSQL 17: ERROR: invalid reference to FROM-clause entry for table "emp"
  • MySQL 8.4: ERROR 1054 (42S22): Unknown column 'emp.dept_id' in 'on clause'

dept JOIN emp e2 が先に評価されるので、ON の中から emp.dept_id を参照できない、という理屈です。MySQL のマニュアルにもこの挙動と「カンマ演算子を避けて JOIN を使う」という回避策が明記されています。既存のカンマ結合クエリに JOIN で 1 テーブル足そうとして踏む、地味に困る罠です。

SELECT * で結合列が重複する

もうひとつ細かい違いとして、カンマ結合(と ON を使った JOIN)では SELECT * の結果に両テーブルの dept_id が 2 回現れます。先ほどの USING(dept_id) では結合列が 1 つにまとめられて 1 回しか出てこなかったのと対照的です。

idnamedept_iddept_iddept_name
1佐藤1010営業部
2鈴木2020開発部

結果をそのままアプリやツールに渡す場合、同名列が 2 本あると列の取り違えや「重複する列名」エラーの原因になります。JOIN 構文なら USING でこの重複を避けられます。

Oracle の旧記法を使っている場合

Oracle には、カンマ結合の WHERE に (+) を付けて外部結合を表す独自の旧記法があります(WHERE emp.dept_id = dept.dept_id(+) のような書き方)。これも「JOIN の省略形」ではなく Oracle 固有の古い構文で、両側に (+) を付けられない(ORA-01468)などの制限があります。ANSI 構文への書き換え対応表を Oracle の JOIN の書き方 — 旧記法 (+) と ANSI 構文の対応表 にまとめたので、Oracle の方はそちらをどうぞ。

さいごに

JOIN = INNER JOINLEFT JOIN = LEFT OUTER JOIN で、INNER・OUTER の省略は結果に一切影響しません。省略するかは好みとチームの流儀の問題です。一方、カンマ結合(FROM a, b)は省略形ではなく旧スタイルで、JOIN との混在エラーや SELECT * の列重複という実害があるので、新規のクエリは JOIN 構文で書くのが無難です。

あわせて読みたい: