관계대수(relational algebra)는 릴레이션에 연산을 차례로 적용해 원하는 릴레이션을 구하는 언어입니다. 행을 고르는 셀렉트(σ), 열을 고르는 프로젝트(π), 두 릴레이션을 잇는 조인(⋈), 나누는 쪽의 값을 모두 가진 것만 남기는 디비전(÷) 넷을 순수 관계 연산자라고 합니다.
3학년 학생의 이름을 구하려면, 학생 표에서 학년이 3인 행을 고른 뒤 그 행에서 이름 열만 남기면 됩니다.
관계대수는 이런 일을 기호로 적습니다.
무엇을 먼저 하고 무엇을 다음에 할지 순서까지 적으므로 절차적 언어라고 합니다.
연산의 입력도 릴레이션이고 결과도 릴레이션입니다. 그래서 한 연산의 결과에 다른 연산을 이어 걸 수 있습니다.
셀렉트·프로젝트·조인·디비전 넷은 릴레이션을 위해 만든 연산이라 순수 관계 연산자라고 부릅니다. 합집합·교집합처럼 집합에서 가져온 연산은 일반 집합 연산자라고 하고, 다음 레슨 관계대수: 집합 연산과 카티션 곱에서 봅니다.
시험은 기호의 이름과 뜻, 식이 내는 결과 릴레이션을 묻습니다.
책과 시험지는 σ·π 뒤의 조건이나 속성을 기호 오른쪽 아래에 작게 씁니다. 이 레슨은 한 줄로 띄어 σ 학년=3 (학생)처럼 씁니다.
1셀렉트(σ)
셀렉트(SELECT, σ)는 조건에 맞는 튜플만 고릅니다. σ는 그리스 문자 시그마입니다. σ 학년=3 (학생)은 학년이 3인 튜플 101·105·106만 남깁니다. 표를 가로로 자르므로 수평 연산이라고도 합니다. 속성은 4개 그대로입니다.
2프로젝트(π)
프로젝트(PROJECT, π)는 고른 속성만 남깁니다. π는 그리스 문자 파이입니다. π 학년 (학생)은 학년 열만 남깁니다. 표를 세로로 자르므로 수직 연산이라고도 합니다.
남은 학년 값은 3·2·2·1·3·3·1입니다. 결과도 릴레이션이라 같은 튜플이 둘일 수 없습니다. 그래서 겹치는 값은 하나만 남아 1·2·3 세 튜플이 됩니다.
식은 괄호 안쪽부터 계산합니다. π 이름 (σ 학년=3 (학생))은 먼저 3학년 세 명을 고르고, 그 결과에서 이름만 남깁니다. 결과는 김민수·최민준·정하윤입니다.
3조인(⋈)
조인(JOIN, ⋈)은 두 릴레이션에서 공통 속성의 값이 같은 튜플끼리 이어 붙입니다. ⋈는 나비넥타이 모양의 기호입니다. 학생 ⋈ 학과는 학과코드가 같은 학생과 학과를 잇습니다. 학과코드가 NULL인 107과 학생이 없는 학과 BA는 짝이 없어 빠지고, 튜플 6개가 남습니다. 공통 속성을 한 번만 남기는 조인을 자연 조인(natural join)이라고 합니다. 그래서 속성은 4 + 3 − 1 = 6개입니다.
4디비전(÷)
디비전(DIVISION, ÷)은 나뉘는 릴레이션 R에서, 나누는 릴레이션 S의 값을 모두 가진 튜플만 남깁니다. 여기서 R은 수강에서 학번과 과목코드만 고른 π 학번, 과목코드 (수강)이고, S는 과목코드 셋인 π 과목코드 (과목)입니다. R을 학번마다 묶으면 학생마다 들은 과목이 보입니다.
S의 세 과목 DS·OS·NW를 모두 가진 학번은 101뿐입니다. 그래서 R ÷ S의 결과는 101 하나입니다. 결과의 속성은 R의 속성(학번, 과목코드)에서 S의 속성(과목코드)을 뺀 학번입니다. '모든 과목을 들은 학생'처럼 '모두'가 들어간 질문이 디비전입니다.
예제
관계대수 식과 같은 결과를 내는 SQL을 나란히 봅니다. SQL은 13단원부터 배우니, 여기서는 결과 표가 식의 결과와 같은지만 봐도 됩니다. 관계대수의 결과는 순서가 없는 집합입니다. 결과를 맞춰 보려고 SQL 끝에 ORDER BY를 붙였습니다.
셀렉트
관계대수: σ 학년=3 (학생)
SELECT *
FROM 학생
WHERE 학년 = 3
ORDER BY 학번;
| 학번 | 이름 | 학년 | 학과코드 |
|---|---|---|---|
| 101 | 김민수 | 3 | CS |
| 105 | 최민준 | 3 | EE |
| 106 | 정하윤 | 3 | EE |
셀렉트(σ)는 SQL의 WHERE에 해당합니다. 이름이 같은 SQL의 SELECT 절이 아닙니다.
프로젝트
관계대수: π 학년 (학생)
SELECT DISTINCT 학년
FROM 학생
ORDER BY 학년;
| 학년 |
|---|
| 1 |
| 2 |
| 3 |
SQL의 SELECT 절이 프로젝트(π)에 해당합니다. 다만 SQL은 겹치는 행을 그대로 두므로, 프로젝트와 같은 결과를 얻으려면 DISTINCT를 붙입니다. DISTINCT가 없으면 일곱 행이 나옵니다.
식 합치기
관계대수: π 이름 (σ 학년=3 (학생))
SELECT 이름
FROM 학생
WHERE 학년 = 3
ORDER BY 학번;
| 이름 |
|---|
| 김민수 |
| 최민준 |
| 정하윤 |
조인
관계대수: π 이름, 학과명 (학생 ⋈ 학과)
속성이 많아 이름과 학과명만 남겼습니다. SQL의 NATURAL JOIN이 자연 조인입니다.
SELECT 이름,
학과명
FROM 학생
NATURAL JOIN 학과
ORDER BY 학번;
| 이름 | 학과명 |
|---|---|
| 김민수 | 컴퓨터 |
| 이서준 | 컴퓨터 |
| 김지민 | 컴퓨터 |
| 박서연 | 전자 |
| 최민준 | 전자 |
| 정하윤 | 전자 |
107 강도현은 학과코드가 NULL이라 이을 학과가 없어 빠졌습니다.
디비전
관계대수는 다음과 같습니다.
π 학번, 과목코드 (수강)
÷ π 과목코드 (과목)
SQL에는 디비전 연산자가 없습니다. '모든 과목을 들었다'를 '듣지 않은 과목이 하나도 없다'로 바꿔 쓰면, 세 과목을 다 들은 101 김민수만 남습니다.
SQL로 확인하기
같은 결과를 내려면 NOT EXISTS를 두 겹 씁니다. 괄호 안의 SELECT(서브쿼리)는 14단원 서브쿼리에서 배웁니다.
SELECT S.학번,
S.이름
FROM 학생 S
WHERE NOT EXISTS (
SELECT *
FROM 과목 C
WHERE NOT EXISTS (
SELECT *
FROM 수강 E
WHERE E.학번 = S.학번
AND E.과목코드
= C.과목코드
)
);| 학번 | 이름 |
|---|---|
| 101 | 김민수 |
- 바깥에서 학생을 하나씩, 가운데에서 과목을 하나씩 잡습니다.
- 안쪽은 그 학생이 그 과목을 들은 수강 행을 찾습니다.
- 들은 행이 없는 과목이 하나도 없는 학생만 남습니다. SQL은 학생 표에서 시작해 이름까지 함께 보였습니다.
시험 포인트
- 필기: 기호와 이름, 하는 일을 짝짓습니다 — σ 셀렉트는 조건에 맞는 튜플(수평), π 프로젝트는 고른 속성(수직, 겹치는 튜플은 하나로), ⋈ 조인은 공통 속성으로 잇기(자연 조인은 공통 속성을 한 번만), ÷ 디비전은 나누는 쪽 값을 모두 가진 튜플입니다. 이 넷이 순수 관계 연산자입니다. 관계대수는 연산 순서를 적는 절차적 언어이고, 식은 안쪽부터 계산합니다. 식을 주고 결과 릴레이션이나 튜플 수를 묻습니다.
- 실기: 연산의 이름과 기호를 씁니다 — 셀렉트(SELECT, σ)·프로젝트(PROJECT, π)·조인(JOIN, ⋈)·디비전(DIVISION, ÷). 표를 주고 디비전의 결과를 쓰게 하기도 합니다.
확인 문제
1. 디비전(÷)으로 풀어야 하는 물음을 고르세요.
- ① 공학관에 있는 학과의 학생은 누구인가
- ② 1학년이 들은 과목을 빠짐없이 들은 3학년은 누구인가
- ③ 과목을 둘 이상 들은 학생은 누구인가
- ④ 학생 표에서 학번과 이름만 뽑으면 어떤 릴레이션인가
정답
②입니다. 한쪽 릴레이션의 값(1학년이 들은 과목)을 하나도 빠뜨리지 않고 가진 튜플만 남기는 물음이 디비전입니다.
- ① 조건으로 행을 고르고(σ) 두 릴레이션을 잇는(⋈) 물음입니다.
- ③ '모두 가졌는가'가 아니라 '몇 개인가'를 묻는 물음입니다. 디비전은 나누는 쪽의 값을 빠짐없이 가졌는지 보는 연산이라 이 물음에는 맞지 않습니다.
- ④ 고른 속성만 남기는 프로젝트(π) 물음입니다.
2. 학과 표(학과코드, 학과명, 건물)와 수강 표에 연산 하나씩을 걸어 다음 결과를 얻었습니다. (가)~(라)에 쓴 연산의 이름과 기호를 한글 이름과 영문, 기호로 함께 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.
- (가) 학과 표에서 건물이 '경영관'인 한 행만 남고, 속성은 셋 그대로입니다.
- (나) 학과 표에서 건물 속성만 남았고, 튜플은 셋에서 둘로 줄었습니다.
- (다) 수강 표와 과목 표를 과목코드가 같은 튜플끼리 이어 붙여 차수가 3 + 4 − 1 = 6이 되었습니다.
- (라) 수강 표에서 학번과 과목코드만 남긴 릴레이션에 과목 표의 과목코드 셋을 걸었더니, 결과의 속성이 학번 하나만 남았습니다.
정답
받는 답: (가) 셀렉트(SELECT, σ) · (나) 프로젝트(PROJECT, π) · (다) 조인(JOIN, ⋈) · (라) 디비전(DIVISION, ÷)
(가)의 실마리는 '조건에 맞는 튜플만 남고 속성은 그대로', (나)는 '속성이 줄고 겹치는 튜플이 하나로 합쳐졌다'입니다. 학과 셋의 건물은 공학관·공학관·경영관이라 둘로 줄었습니다. (다)는 '공통 속성을 한 번만 남기고 이어 붙였다', (라)는 '결과에서 나누는 쪽 속성이 빠졌다'입니다.
- 같은 이름의 다른 꼴: 기호만 쓴 꼴이나 이름만 쓴 꼴 — 문제가 이름과 기호를 함께 쓰라고 했습니다.
- 틀리는 꼴 프로젝트 — (가)에: 속성을 고르는 연산입니다. (가)는 속성이 셋 그대로이고 튜플이 줄었습니다.
- 틀리는 꼴 셀렉트 — (나)에: 튜플을 고르는 연산입니다. (나)는 속성이 하나로 줄었습니다.
3. 다음 두 식의 결과를 구하세요. 튜플 수까지 쓰세요. 학생 표는 그림과 예제에서 본 일곱 행 그대로이고, 식이 함께 보는 세 표는 아래와 같습니다.
학과 표
| 학과코드 | 학과명 | 건물 |
|---|---|---|
| CS | 컴퓨터 | 공학관 |
| EE | 전자 | 공학관 |
| BA | 경영 | 경영관 |
과목 표
| 과목코드 | 과목명 | 학점 |
|---|---|---|
| DS | 자료구조 | 3 |
| OS | 운영체제 | 3 |
| NW | 네트워크 | 2 |
수강 표
| 학번 | 과목코드 | 점수 |
|---|---|---|
| 101 | DS | 85 |
| 101 | OS | 75 |
| 101 | NW | 80 |
| 102 | DS | 70 |
| 102 | OS | 60 |
| 103 | DS | 65 |
| 103 | NW | 55 |
| 104 | OS | 75 |
| 104 | NW | 95 |
| 105 | DS | 100 |
| 105 | NW | 90 |
| 107 | NW | 50 |
(가) π 건물
(σ 학년=3 (학생) ⋈ 학과)
(나) π 학번, 과목코드
(σ 점수>=70 (수강))
÷ π 과목코드
(σ 학점=3 (과목))
정답
(가) 공학관, 1개 · (나) 101, 1개입니다.
- (가) 3학년은 101(CS)·105(EE)·106(EE)입니다. 학과를 이어 붙이면 건물이 공학관·공학관·공학관이고, 프로젝트는 겹치는 튜플을 하나로 남기므로 1개입니다. 3개로 답하는 실수가 많습니다.
- (나) 70점 이상인 수강만 남기면 101은 DS·OS·NW, 102는 DS, 104는 OS·NW, 105는 DS·NW입니다. 나누는 쪽은 학점이 3인 DS·OS 둘이고, 둘을 모두 가진 학번은 101뿐입니다.
- (나) 102는 OS를 들었지만 60점이라 걸러졌습니다. 나뉘는 쪽을 먼저 거르면 결과가 달라집니다.