관계대수 — SQL 뒤에 숨은 연산자들
관계대수(Relational Algebra)는 관계형 데이터베이스에서 원하는 결과를 얻기 위해 테이블(관계)에 적용하는 연산의 집합이다. SQL이 “무엇을 원하는지”만 선언하는 비절차적 언어라면, 관계대수는 “어떤 순서로 어떤 연산을 거쳐 얻는지”를 명시하는 절차적 언어다. 정처기 필기에서는 연산자 기호와 이름을 매칭하는 문제, 그리고 select와 project를 헷갈리게 하는 보기가 단골로 나온다.
순수 관계 연산자
일반 집합 연산과 별개로, 관계대수에만 있는 연산자 두 가지가 핵심이다.
- select(σ, 셀렉트): 조건을 만족하는 행(튜플)을 골라낸다.
σ_점수>=80(성적)은 성적 테이블에서 점수가 80 이상인 행만 뽑는다. - project(π, 프로젝트): 지정한 열(속성)만 뽑아 새 관계를 만든다.
π_이름,학과(학생)은 학생 테이블에서 이름과 학과 열만 남긴다. 중복된 행은 제거된다.
이름과 동작이 반대로 느껴지기 쉽다. σ는 “가로로” 행을 자르고, π는 “세로로” 열을 자른다고 기억하면 헷갈리지 않는다. SQL로 옮기면 σ는 WHERE 절, π는 SELECT 절에 대응한다 — 정작 SQL의 SELECT라는 이름은 관계대수의 project에 해당한다는 점이 시험에서 자주 걸린다.
일반 집합 연산자
- 합집합(∪, union): 두 관계의 행을 합친다. 속성 수와 각 속성의 도메인이 같아야 한다는 합병 가능(union-compatible) 조건이 붙는다.
- 차집합(−, difference): 한 관계에는 있고 다른 관계에는 없는 행만 남긴다.
- 교집합(∩, intersection): 두 관계에 공통으로 있는 행만 남긴다. select·project·union·difference·cartesian product 다섯 개로 유도할 수 있어 기본 연산자에서 빠지기도 한다.
- 카티션 프로덕트(×, cartesian product): 두 관계의 모든 행 조합을 만든다. 두 관계의 행 수를 곱한 만큼 결과가 나온다.
유도 연산자 — join
join(⋈)은 카티션 프로덕트 뒤에 select를 붙인 것과 같은 결과를 내는 유도 연산자다.
- 세타 조인(θ-join): 임의의 비교 조건(=, >, < 등)으로 두 관계를 결합한다.
- 동등 조인(equi-join): 조건이 전부 등호(=)인 세타 조인이다.
- 자연 조인(natural join): 동등 조인 결과에서 중복되는 공통 속성 열을 하나로 합쳐 제거한다. 실무에서 가장 흔히 쓰는 형태다.
예를 들어 학생(학번, 이름)과 수강(학번, 과목)이 있을 때 학생 ⋈ 수강은 학번이 같은 행끼리 묶어 학번 열을 하나만 남긴 결과를 낸다.
시험에 자주 나오는 포인트
- select와 project를 SQL의 WHERE/SELECT와 짝지어 헷갈리지 않게 정리해 둔다. project는 이름 그대로 SQL SELECT 절과 대응한다.
- union·difference·intersection은 합병 가능 조건(속성 수·도메인 동일)이 없으면 성립하지 않는다는 점이 오답 보기로 나온다.
- 관계대수는 절차적, 관계해석(Relational Calculus)은 비절차적(선언적)이라는 대비도 함께 묻는다. SQL은 관계해석에 가까운 선언적 문법을 쓰지만 내부적으로는 관계대수 연산으로 변환되어 실행된다.
- 자연 조인은 동등 조인과 달리 중복 속성이 결과에 한 번만 남는다는 차이를 구분하는 문제가 나온다.
이 글에 대한 의견은 아래 댓글로 남겨주세요 (GitHub 계정 필요). 로그인 없이 남기고 싶다면