はじめに
こんにちは!今日はデータベースの関係モデルで使われる基本的な演算についてお話しします。普段SQLを使っていると、複雑なJOINや条件検索を当たり前のように行いますが、その裏側には「関係代数」と呼ばれる理論的な基礎があります。
8つの基本演算(和、差、共通、直積、射影、選択、結合、商)を理解しておくと、なぜSQLがあのような構文になっているのかや、どうして特定の操作が可能なのかがクリアになります。これからの学習や実務に生かせると思うので、ぜひ最後まで読んでみてください!
本文
和両立(Union Compatibility)
和、差、共通といった集合系の演算を行うには、和両立(Union Compatibility)の条件が必要です。すなわち、2つの関係RとSが同じ次数(列数)を持ち、対応する列が同じドメインを持っている必要があります。これを満たして初めてUNION、EXCEPT、INTERSECT が適用できます。
和(UNION)
2つの和両立な関係RとSについて、R∪Sは、RまたはSに含まれるタプルをすべて集めた関係です。
R:
| ID | NAME |
|---|---|
| 1 | Alice |
| 2 | Bob |
S:
| ID | NAME |
|---|---|
| 2 | Bob |
| 3 | Carol |
-- R∪S
SELECT * FROM R
UNION
SELECT * FROM S;
結果
R∪S:
| ID | NAME |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Carol |
差(DIFFERENCE)
R−Sは、Rに含まれるがSに含まれないタプル集合です。
-- R−S
SELECT * FROM R
EXCEPT
SELECT * FROM S;
結果
R-S: ID=1,Aliceのみ残る。ID=3, Carolは無視される。
| ID | NAME |
|---|---|
| 1 | Alice |
共通(INTERSECTION)
R∩Sは、RとSの両方に含まれるタプル集合です。
-- R∩S
SELECT * FROM R
INTERSECT
SELECT * FROM S;
結果
R∩SはID=2,Bobのみ
| ID | NAME |
|---|---|
| 2 | Bob |
直積(CARTESIAN PRODUCT)
R×SはRの各タプルとSの各タプルを全組み合わせで生成した関係です。
-- R×S
SELECT * FROM R CROSS JOIN S;
結果
R×SはRの行数×Sの行数のタプルが生成されます
| R.ID | R.NAME | S.ID | S.NAME |
|---|---|---|---|
| 1 | Alice | 2 | Bob |
| 1 | Alice | 3 | Carol |
| 2 | Bob | 2 | Bob |
| 2 | Bob | 3 | Carol |
射影(PROJECTION)
射影は関係から特定の列を取り出す操作です。
-- R'(NAME)
SELECT NAME FROM R;
結果
R(ID,NAME)に対しNAME列のみ取得すると
| NAME |
|---|
| Alice |
| Bob |
選択(SELECTION)
選択は関係から条件を満たす行を抽出する操作です。
R:
| ID | NAME | AGE |
|---|---|---|
| 1 | Alice | 18 |
| 2 | Bob | 25 |
| 3 | Eve | 22 |
| 4 | Tom | 20 |
-- R'(ID, NAME, AGE)
SELECT * FROM R WHERE AGE > 20;
結果
RからAGE>20の行のみ抽出
| ID | NAME | AGE |
|---|---|---|
| 2 | Bob | 25 |
| 3 | Eve | 22 |
結合(JOIN)
結合は2つの関係を共通の属性で結びつける操作です。最も基本的な自然結合では、直積から対応する属性値が等しい行を抽出し、重複列を除去します。
R:
| ID | NAME |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 4 | Dave |
S:
| ID | PRICE |
|---|---|
| 1 | 100 |
| 2 | 200 |
| 3 | 150 |
SELECT R.ID, R.NAME, S.PRICE
FROM R INNER JOIN S ON R.ID = S.ID;
結果
R(ID,NAME),S(ID,PRICE)でRとSをIDで結合すると、対応するIDの行がマージされます。
| ID | NAME | PRICE |
|---|---|---|
| 1 | Alice | 100 |
| 2 | Bob | 200 |
商(DIVISION)
商は、R÷Sで「Sに含まれる値の組合せをすべて含むRの列集合」を抽出する操作です。SQLに直接対応する構文はなく、相互の包含関係を確認する副問合せなどで実装します。
R:
| A | B |
|---|---|
| 1 | X |
| 1 | Y |
| 1 | Z |
| 2 | X |
| 2 | Y |
| 3 | X |
S:
| B |
|---|
| X |
| Y |
-- R÷S
SELECT DISTINCT A
FROM R
WHERE NOT EXISTS (
SELECT B FROM S
WHERE B NOT IN (
SELECT B FROM R WHERE R.A = A
)
);
結果
R(A,B), S(B)の場合、R÷Sは「SにあるBすべてに対応するA」を求めます。
| A |
|---|
| 1 |
| 2 |
まとめ
8つの基本演算は、データベースの考え方を形作る大切な要素です。これらを理解しておくと、SQLで複雑な問い合わせを書く際にも「なぜこう書くのか」「どうしてこの処理が可能なのか」といった理論的な背景がわかり、より納得しながらコーディングできるようになります。
もちろん、実際の現場では必ずしも理論どおりにいかないこともありますが、基礎理論に基づいて考えることで、より良い設計やクエリチューニングに役立ちます。明日は結合演算です!