ON 句と USING 句の使い方
juchu受注
| juchu_id | kokyaku_id |
|---|---|
| 1001 | 1 |
| 1002 | 2 |
| … | |
kokyaku顧客
| kokyaku_id | kokyaku_name |
|---|---|
| 1 | 青葉工業 |
| 2 | 白樺物産 |
| 5 | 三田商事✕ |
| … | |
ONつないだ結果
| juchu_id | kokyaku_id | kokyaku_name |
|---|---|---|
| 1001 | 1 | 青葉工業 |
| 1002 | 2 | 白樺物産 |
| … | ||
- kokyaku_nameのように、右の表の列が左の表にくっつくのが結合です。
- 受注 10 行 → つないだ結果 10 行(行数は変わりません)
- 取り消し線= 相手がいないので結果に出てこない行
- 受注側に取り消し線が無いのは、必ず顧客に紐づいているためです。
ON に書くのは「この列とこの列が同じ行を指している」という対応関係です。絞り込みの条件ではありません。
`ON` は「どの行とどの行をつなぐか」を決める場所です。 WHERE(つないだ結果から何を残すか)とは役割も評価される順番も違います。内部結合では結果が同じになることが多いのですが、外部結合では答えが変わります。
この書き方が使えない製品があります そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite / Oracle Database / IBM Db2
- SQL Server では使えません(JOIN ... USING (列))
このページの実行結果と図は、すべて本物のデータベースに同じ SQL を流して得たものです。手で書いた「たぶんこうなる」ではありません。
01ON に書くのは「対応関係」
結論: `ON` には「どの列どうしが同じものを指すか」を書きます。
たいていは外部キーと主キーの対応、つまり ON 子.親id = 親.id の形になります。等号 1 つで足りることがほとんどです。
複数の列で対応させる場合は AND でつなぎます。受注番号と行番号のように、組み合わせで 1 行が決まる表を結合するときに使います。
SELECT j.juchu_id, s.shohin_name, m.suryo何を出すかFROM juchu j主となる表JOIN juchu_meisai mつなぐ相手(1)ON m.juchu_id = j.juchu_id対応関係(1)JOIN shohin sつなぐ相手(2)ON s.shohin_id = m.shohin_id対応関係(2)ORDER BY j.juchu_id, m.gyo_no並び順
JOIN が 2 つあれば ON も 2 つ。1 つでも欠けると、その分だけ総当たりになります。
SELECT j.juchu_id, s.shohin_name, m.suryo
FROM juchu j
JOIN juchu_meisai m ON m.juchu_id = j.juchu_id
JOIN shohin s ON s.shohin_id = m.shohin_id
ORDER BY j.juchu_id, m.gyo_no;| juchu_id | shohin_name | suryo |
|---|---|---|
| 1001 | ノート | 20 |
| 1001 | ボールペン | 30 |
| 1002 | デスクチェア | 2 |
| 1002 | 書棚 | 1 |
| 1003 | デスクライト | 4 |
| 1003 | キーボード | 2 |
(17 行 … うち先頭 6 行を表示)
02内部結合なら ON と WHERE の結果は同じ
内部結合では、絞り込みの条件を ON に書いても WHERE に書いても同じ結果になります。
対応が無い行はどのみち消えるので、「つなぐ前に落とす」のと「つないだ後に落とす」のとで差が出ないからです。
この経験があるために、外部結合でも同じだと思い込むのが次の節の事故につながります。
SELECT j.juchu_id, k.kokyaku_name
FROM juchu j
JOIN kokyaku k ON k.kokyaku_id = j.kokyaku_id AND j.status = 'done'
ORDER BY j.juchu_id;| juchu_id | kokyaku_name |
|---|---|
| 1001 | 青葉工業 |
| 1002 | 白樺物産 |
| 1003 | 青葉工業 |
| 1005 | 赤坂商会 |
(8 行 … うち先頭 4 行を表示)
SELECT j.juchu_id, k.kokyaku_name
FROM juchu j
JOIN kokyaku k ON k.kokyaku_id = j.kokyaku_id
WHERE j.status = 'done'
ORDER BY j.juchu_id;| juchu_id | kokyaku_name |
|---|---|
| 1001 | 青葉工業 |
| 1002 | 白樺物産 |
| 1003 | 青葉工業 |
| 1005 | 赤坂商会 |
(8 行 … うち先頭 4 行を表示)
03⚠️ よくある間違い:外部結合では ON と WHERE で答えが変わる
ここが本題です。 外部結合では、同じ条件を ON に書くか WHERE に書くかで結果が変わります。
- `ON` に書く … 条件に合わない相手は「つながなかった」ことになる。左の行は残る(相手側が
NULL) - `WHERE` に書く … つないだ後で行ごと落とす。左の行が消える
WHERE に書くと、せっかく外部結合にした意味が無くなり、実質内部結合と同じになります。
判断の仕方: その条件が「つなぐ相手を選ぶ条件」なら ON、「最終的に残す行を選ぶ条件」なら WHERE です。
SELECT k.kokyaku_name, j.juchu_id, j.status
FROM kokyaku k
LEFT JOIN juchu j ON j.kokyaku_id = k.kokyaku_id
WHERE j.status = 'done'
ORDER BY k.kokyaku_id;| kokyaku_name | juchu_id | status |
|---|---|---|
| 青葉工業 | 1008 | done |
| 青葉工業 | 1003 | done |
| 青葉工業 | 1001 | done |
| 白樺物産 | 1006 | done |
| 白樺物産 | 1002 | done |
(8 行 … うち先頭 5 行を表示)
外部結合にしたのに、受注が 1 件も無い顧客が結果に出てきません。
SELECT k.kokyaku_name, j.juchu_id, j.status
FROM kokyaku k
LEFT JOIN juchu j ON j.kokyaku_id = k.kokyaku_id AND j.status = 'done'
ORDER BY k.kokyaku_id;| kokyaku_name | juchu_id | status |
|---|---|---|
| 青葉工業 | 1008 | done |
| 青葉工業 | 1001 | done |
| 青葉工業 | 1003 | done |
| 白樺物産 | 1006 | done |
| 白樺物産 | 1002 | done |
(9 行 … うち先頭 5 行を表示)
受注が無い顧客も残り、受注側の列が NULL になっています。顧客の一覧としてはこちらが正しい形です。
04列名が同じなら USING で短く書ける
つなぐ列の名前が両方の表でまったく同じときに限り、`USING (列名)` と書けます。
USING を使うと結合列は 1 本にまとまるので、SELECT * したときに同じ列が 2 回出てきません。列名を表名で修飾する必要もなくなります。
ただし使えない製品があります(実測では SQL Server が非対応)。また、名前がたまたま同じだけの列を誤ってつないでしまう危険もあります。迷ったら `ON` を使ってください。 ON は調べたすべての製品で通ります。
SELECT juchu_id, kokyaku_name
FROM juchu
JOIN kokyaku USING (kokyaku_id)
ORDER BY juchu_id;| juchu_id | kokyaku_name |
|---|---|
| 1001 | 青葉工業 |
| 1002 | 白樺物産 |
| 1003 | 青葉工業 |
| 1004 | 黒松システム |
(10 行 … うち先頭 4 行を表示)
kokyaku_id が 1 本にまとまるので、表名を付けずに書けています。
⚠️ この書き方は SQL Server では使えません(JOIN ... USING (列))。製品ごとの対応表
05等号以外も書ける
ON に書けるのは等号だけではありません。真偽が決まる式なら何でも書けます。
範囲で対応させる(金額が階級表のどの区分に入るか)、不等号で組み合わせを作る(自分より前の行だけ)といった使い方があります。
ただし等号以外は照合の手間が大きく、行数が多いと遅くなります。まずは等号で書けないかを考えてください。
SELECT a.shohin_name AS yasui, b.shohin_name AS takai
FROM shohin a
JOIN shohin b ON a.price < b.price AND a.category = b.category
ORDER BY a.category, a.price, b.price;| yasui | takai |
|---|---|
| 書棚 | デスクチェア |
| デスクライト | キーボード |
| ボールペン | ノート |
| ボールペン | 付箋 |
| ノート | 付箋 |
(5 行)
同じ表を 2 回使っています(自己結合)。不等号で組み合わせを作る例です。
自分で打ってみる
このページの例と同じデータが入った本物のデータベースを、この場(あなたのブラウザの中)で起動できます。打った SQL がサーバーへ送られることはありません。
押すと初回だけ約 9MB を読み込みます(2 回目以降はキャッシュされます)。
解いてみる
読んだだけでは書けるようになりません。実行結果で採点します。
関連するトピック
- INNER JOINON を使う基本の形です。
- LEFT / RIGHT OUTER JOINON と WHERE の違いが結果に出るのは外部結合のときです。
- CROSS JOINON を書き忘れると、これと同じ総当たりになります。
- WHERE 句つないだ後の絞り込み。役割の違いを押さえてください。
根拠(一次情報)
- PostgreSQL 18 マニュアル: 問い合わせ — 結合テーブル(ON / USING)一次情報・確認 2026-07-28
- SQLite: SELECT(join-constraint)一次情報・確認 2026-07-28
- Oracle Database SQL Language Reference: SELECT(join_clause)一次情報・確認 2026-07-28