Relational Algebra & Tuple Relational Calculus
Relational Algebra is a procedural query language providing operations to manipulate relations. It forms the theoretical foundation of SQL. Core operations: Selection (σ), Projection (π), Cartesian Product (×), Union (∪), Set Difference (−), and Rename (ρ). Derived operations include Join (⋈), Intersection (∩), and Division (÷). Tuple Relational Calculus (TRC) is a non-procedural counterpart — you describe WHAT you want without specifying HOW. Both are tested heavily in GATE DBMS.
The mathematical query language behind SQL — the theory every database professional must know.
Category: Database Management Systems
Real-life analogy: SQL behind the scenes
Every SQL query you write is translated by the DBMS into a relational algebra expression tree, optimized, then executed. Knowing RA means you understand exactly what happens for SELECT with WHERE, JOIN, and GROUP BY. You can predict query behavior, write better SQL, and explain execution plans.
Core operations with SQL equivalents
| Operation | Symbol | SQL equivalent | Example |
|---|---|---|---|
| Selection | σ_cond(R) | WHERE clause | σ_Age>25(Employee) — rows where Age > 25 |
| Projection | π_attrs(R) | SELECT columns | π_Name,Salary(Employee) — only those columns |
| Cartesian Product | R × S | CROSS JOIN | Employee × Department — every combination |
| Union | R ∪ S | UNION | All students from two departments combined |
| Set Difference | R − S | EXCEPT | AllStudents − PassedStudents |
| Rename | ρ_name(R) | AS alias | ρ_Emp(Employee) |
| Natural Join | R ⋈ S | NATURAL JOIN | Join on all common attributes automatically |
| Theta Join | R ⋈_cond S | JOIN ON condition | Emp ⋈_{E.DeptID=D.DeptID} Dept |
| Division | R ÷ S | NOT EXISTS subquery | Students enrolled in ALL courses |
-- R(A): Employee(EmpID, Name, DeptID, Salary)
-- R(B): Department(DeptID, DeptName, Location)
-- 1. Selection + Projection
-- RA: π_Name,Salary(σ_Salary>50000(Employee))
SELECT Name, Salary FROM Employee WHERE Salary > 50000;
-- 2. Theta Join (most common join type)
-- RA: σ_E.DeptID=D.DeptID(Employee × Department)
SELECT E.Name, D.DeptName
FROM Employee E JOIN Department D ON E.DeptID = D.DeptID;
-- 3. Union: employees in Dept 1 OR Dept 2
-- RA: π_EmpID(σ_DeptID=1(Employee)) ∪ π_EmpID(σ_DeptID=2(Employee))
SELECT EmpID FROM Employee WHERE DeptID = 1
UNION
SELECT EmpID FROM Employee WHERE DeptID = 2;
-- 4. Set Difference: employees NOT in Dept 1
-- RA: π_EmpID(Employee) − π_EmpID(σ_DeptID=1(Employee))
SELECT EmpID FROM Employee
EXCEPT
SELECT EmpID FROM Employee WHERE DeptID = 1;
-- 5. Division: employees who worked on ALL projects
-- RA: WorksOn ÷ Project
SELECT DISTINCT w1.EmpID FROM WorksOn w1
WHERE NOT EXISTS (
SELECT ProjID FROM Project
EXCEPT
SELECT w2.ProjID FROM WorksOn w2 WHERE w2.EmpID = w1.EmpID
);
Tuple Relational Calculus (TRC)
TRC syntax: {t | P(t)} — the set of all tuples t that satisfy predicate P. TRC is non-procedural: you declare WHAT you want, not HOW to compute it. Uses ∃ (existential) and ∀ (universal) quantifiers.
| RA expression | TRC equivalent | SQL equivalent |
|---|---|---|
| σ_Age>25(Employee) | {t | t ∈ Employee ∧ t.Age > 25} | SELECT * FROM Employee WHERE Age > 25 |
| π_Name(Employee) | {t.Name | t ∈ Employee} | SELECT Name FROM Employee |
Safe vs unsafe TRC expressions: TRC can express "unsafe" queries returning infinite results: {t | t ∉ Employee} — all tuples NOT in Employee is infinite. Safe TRC only produces values from the active domain. SQL is always safe by design.
Min/max result sizes — the classic GATE numerical
GATE loves asking "relation R has m tuples, S has n tuples — what are the minimum and maximum tuples in the result?" The complete cheat sheet (set operations assume union-compatible relations):
| Expression | Minimum tuples | Maximum tuples | When the extremes occur |
|---|---|---|---|
| σ_c(R) | 0 | m | No row satisfies c / every row does |
| π_A(R) | 1 (if m ≥ 1) | m | All rows share the same A-value / all distinct |
| R × S | m·n | m·n | Always exactly m·n |
| R ⋈ S (natural) | 0 | m·n | No matches / both relations constant on the shared attributes |
| R ∪ S | max(m, n) | m + n | One is a subset of the other / disjoint |
| R ∩ S | 0 | min(m, n) | Disjoint / one is a subset of the other |
| R − S | max(0, m − n) | m | S covers as much of R as possible / disjoint |
Equivalence rules — how the optimizer rewrites your query
Query optimizers are relational-algebra rewrite engines. The parser turns SQL into an RA expression tree; the optimizer then applies equivalence rules to find a cheaper but provably identical plan. The single most important rule family is pushing selections down: filtering early shrinks every intermediate result that follows.
- Cascade of σ: σ_c1∧c2(R) ≡ σ_c1(σ_c2(R)) — a compound filter can be split and applied in stages.
- Push σ through join: σ_c(R ⋈ S) ≡ σ_c(R) ⋈ S when c references only R's attributes — filter a million-row table before joining, not after.
- σ + × = ⋈: σ_R.a=S.b(R × S) ≡ R ⋈_{R.a=S.b} S — a selection over a Cartesian product is a theta join; optimizers never actually materialize the product.
- Join commutativity and associativity: R ⋈ S ≡ S ⋈ R and (R ⋈ S) ⋈ T ≡ R ⋈ (S ⋈ T) — this freedom is what join-order optimization explores; for n tables there are Catalan-number-many orders.
- Push π down: discard unneeded columns early to shrink intermediate tuples — but only after keeping the columns later joins still need.
Reading EXPLAIN output: When PostgreSQL's EXPLAIN shows a filter applied at a table scan node underneath a join node, you are watching "push selection below join" in action. The optimizer chose σ-then-⋈ over ⋈-then-σ — exactly the rewrite above, applied automatically.
Sets vs bags, and extended relational algebra
Pure relational algebra is set-based: π_Dept(Employee) automatically deduplicates. SQL uses bag (multiset) semantics: SELECT Dept FROM Employee keeps every duplicate unless you write DISTINCT. This is the single most common source of confusion when translating between RA and SQL — UNION deduplicates (set), UNION ALL does not (bag), and COUNT can differ between the two worlds. Real query engines also need operations Codd's six primitives cannot express, collectively called extended relational algebra:
| Extended operator | Symbol | SQL equivalent | Why the core six cannot express it |
|---|---|---|---|
| Aggregation / grouping | γ | GROUP BY with SUM, COUNT, AVG… | Core RA maps tuples to tuples; it cannot collapse groups into computed values |
| Left / right / full outer join | ⟕ ⟖ ⟗ | LEFT / RIGHT / FULL JOIN | Core joins drop non-matching tuples; outer joins must preserve them with NULL padding |
| Duplicate elimination | δ | DISTINCT | Only meaningful once you admit bags |
| Sorting | τ | ORDER BY | Relations are unordered sets — order is outside the model |
Practice questions (GATE-style)
- Express in RA: names of employees earning more than 50000 in department named "IT". (Answer: π_Name(σ_Salary>50000(Employee ⋈_{E.DeptID=D.DeptID} σ_DeptName="IT"(Department))))
- R has 5 tuples, S has 3 tuples. Maximum tuples in R ⋈ S (natural join on common attribute)? (Answer: 15 if all 5 tuples of R match all 3 of S. Minimum is 0 if no matches.)
- What is R ∪ S where R={(1,a),(2,b)} and S={(2,b),(3,c)}? (Answer: {(1,a),(2,b),(3,c)} — set union removes duplicates.)
- RA is procedural and TRC is non-procedural. What does this mean? (Answer: RA specifies a sequence of operations (HOW to retrieve). TRC specifies a predicate describing desired result (WHAT to retrieve) without specifying retrieval procedure.)
- Express R ÷ S using basic operators. (Answer: R ÷ S = π_R-S(R) − π_R-S((π_R-S(R) × S) − R))
LumiChats can translate any relational algebra expression to SQL and vice versa. Paste an RA expression like π_Name,Salary(σ_DeptID=5(Employee ⋈ Department)) and ask for equivalent SQL with explanation.