はじめに
こんにちは!今日はデータベースの関係モデルで使われる基本的な演算についてお話しします。普段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で複雑な問い合わせを書く際にも「なぜこう書くのか」「どうしてこの処理が可能なのか」といった理論的な背景がわかり、より納得しながらコーディングできるようになります。
もちろん、実際の現場では必ずしも理論どおりにいかないこともありますが、基礎理論に基づいて考えることで、より良い設計やクエリチューニングに役立ちます。明日は結合演算です!