Instiq
第3章 · データ操作とSQL·v1.0.0·更新 2026/7/10·読了目安 約16分

変更要約: 初版

3.1関係代数と関係論理

この節の要点

選択σ射影π結合⋈(自然結合/等結合/外部結合)・和∪差−直積×商÷という関係代数の基本演算と、SQLのクエリがこれらの組み合わせとしてどう解釈されるかを、実務のクエリ設計判断とともに学びます。

関係代数は「関係(表)から関係を作る演算の集合」であり、SQLのSELECT文は内部的にこれらの演算の組み合わせとして解釈できます。DBスペシャリストにとって関係代数を学ぶ意義は、公式を暗記することではなく、目の前のクエリが遅い・意図しない結果になる原因を、演算の順序やコストの観点から説明できるようになることです。この節では各演算の意味と、実務でよく問題になる「結合の種類の選び間違い」を扱います。

3.1.1単項演算:選択と射影

  • 選択(σ)=関係から条件に合う行(タプル)だけを取り出す演算。SQLのWHERE句に相当する。行数は減るが列構成は変わらない。
  • 射影(π)=関係から指定した列(属性)だけを取り出す演算。SQLのSELECT句の列指定に相当する。重複行は本来除去される(数学的な集合の性質)が、SQLのSELECTは既定で重複を残す点に注意(除去するにはDISTINCTが必要)。

3.1.22項演算:和・差・直積・商

  • 和(∪)=2つの関係(属性構成が同じ=和両立)を合わせて重複を除いた関係を作る。SQLのUNIONに相当(重複を残す場合はUNION ALL)。差(−)=一方には存在し他方には存在しない行を取り出す。SQLのEXCEPT(製品によってはMINUS)に相当。
  • 直積(×)=2つの関係の全ての行の組み合わせを作る演算(行数は両者の積)。結合条件を付けずに複数表をFROMに列挙すると直積になり、意図せず巨大な結果セットを生む典型的な事故原因になる。
  • 商(÷)=関係Rを関係Sで割り、「Sの全ての行と組み合わせが揃っている」Rの部分集合を求める演算。「全ての科目に合格した学生」のような全称量化(すべての〜について)を表す問い合わせに対応し、SQLでは二重のNOT EXISTS(該当しない行が存在しないことの確認を2段階行う)で表現するのが定石。

3.1.3結合(⋈):自然結合・等結合・外部結合

  • 結合(⋈)=直積を作った上で結合条件に合う行だけを残す演算(実装上は直積を経由せず効率的に処理される)。等結合=結合条件が等号(=)のもの。自然結合=同名の列を暗黙の結合条件とし、結果から重複列を除去したもの。
  • 内部結合(INNER JOIN)=両方の表に一致する行だけを残す。外部結合(OUTER JOIN)=一致しない行も、もう一方をNULLで埋めて残す。左外部結合(LEFT)=左側の全行を保持、右外部結合(RIGHT)=右側の全行を保持、完全外部結合(FULL)=両側の全行を保持。
  • 自己結合(SELF JOIN)=同一の表を2つの別名(エイリアス)で扱い、行同士を比較する結合。「従業員表の各行に対し、その上司の氏名を同じ従業員表から引く」といった階層構造の展開に使う。
試験ポイント

「選択σ=行の絞込み(WHERE)、射影π=列の絞込み(SELECT)」「直積×に結合条件を付けたのが結合⋈」「商÷は全称量化(すべての〜)に対応しSQLでは二重NOT EXISTSで表現」が最頻出です。外部結合の左右の向き(保持される側)を取り違えないことも重要です。

あるDBAが「全ての必修科目に合格した学生の一覧を出したい」という要件を受けたとします。素直に書くと「学生ごとに合格科目数をカウントし、必修科目数と一致するか比較する」集約的なアプローチも可能ですが、関係代数的には商(÷)の典型例です。SQLでは商を直接表現する構文がないため、二重のNOT EXISTSで組み立てます。
①内側のNOT EXISTSで「その学生がまだ合格していない必修科目」を探す副問合せを書き、
②外側で「そのような未合格科目が1つも存在しない学生」だけを残す、という2段階です。この形は「〜が存在しない、という条件を満たさない行が存在しない」という二重否定になり読みにくいですが、NULLを含む合格科目数の比較で起きがちな数え間違い(履修していない科目とNULLの取り違え)を避けられるという利点があります。一方、集計ベースの方法(COUNTで比較する方法)は書きやすい反面、「対象科目のうち一部が後から追加/削除された場合にCOUNTの基準値も変更が必要」という保守性の課題があり、要件が「必修科目リストが可変」であるなら商(NOT EXISTS二重否定)のほうが要件変更への追従が容易という設計判断になります。このように、同じ結果を得る書き方が複数あっても、保守性・NULL安全性・将来の要件変化への耐性で選択を判断するのがDBスペシャリストの視点です。

演算記号SQL対応
選択σWHERE
射影πSELECT(列指定)
結合JOIN … ON
UNION
EXCEPT(MINUS)
直積×結合条件なしのFROM複数指定
÷二重NOT EXISTS等
注意

ひっかけ: 「自然結合は結合条件を明示しなくても常に正しい結果になる」は誤りです——同名だが意味の異なる列(例:どちらの表にもあるcodeが別の意味)が偶然存在すると誤った結合になる危険があります。また「射影は関係代数でもSQLでも常に重複行を除去する」も誤り=関係代数の射影は重複を除去するが、SQLのSELECTは既定で重複を残すDISTINCTが必要)。

選択/射影/結合/商の図。
問合せの意味論

3.1.4この節のまとめ

  • 選択σは行の絞込み(WHERE)、射影πは列の絞込み(SELECT)に対応する
  • 結合⋈は直積×に条件を付けたもの。自然結合は同名列を暗黙結合するため列名の意味の食い違いに注意
  • 商÷は全称量化(すべての〜)に対応し、SQLでは二重のNOT EXISTSで表現するのが定石

進捗の記録にはログインが必要です。

理解度チェック

(軽い確認用)

Q1. 全ての必修科目に合格した学生を抽出する要件があり、必修科目リストは今後追加・削除される見込みである。この将来の変更に最も追従しやすい実装方針はどれか。

Q2. 2つの表を結合条件なしで`FROM`に列挙してクエリを実行したところ、想定よりはるかに多い行数の結果が返った。この現象の説明として最も適切なものはどれか。

Q3. 従業員表(employees)の各行について、同じ表から上司の氏名を引き当てて一覧表示したい。最も適切な結合方式はどれか。

理解度を確認第3章「データ操作とSQL」の問題を解く