Introduction

Relational algebra is a procedural query language: a query is an expression built from operators that take relations and return a relation. Because the output of every operator is again a relation, operators compose freely, and an expression reads like a pipeline. Every SQL query is translated into an algebra expression before it is optimised and executed, so the algebra is also the vocabulary of query processing.

The algebra uses set semantics: relations have no duplicate tuples, and every operator removes duplicates from its result. This single fact explains several traps, such as the cardinality of a projection. What an expression returns on given tables, how many tuples a join can produce, and which expression expresses a "for all" query (division) are the standard calculations.

Prerequisites

Core concepts

The six basic operators

OperatorNotationResult
Selectionσp(R)\sigma_{p}(R)tuples of RR satisfying predicate pp
ProjectionπA1,…,Ak(R)\pi_{A_1, \ldots, A_k}(R)the listed columns, duplicates removed
UnionR∪SR \cup Stuples in either; RR, SS union-compatible
Set differenceR−SR - Stuples in RR and not in SS; union-compatible
Cartesian productR×SR \times Severy pairing of a tuple of RR with a tuple of SS
RenameρT(B1,…,Bn)(R)\rho_{T(B_1, \ldots, B_n)}(R)same tuples, new relation and attribute names

Union compatibility. RR and SS have the same arity and corresponding attributes have the same domains. Names may differ; the result takes the names of RR.

These six are the fundamental operators: every derived operator can be written with them, and together they make a language relationally complete.

Derived operators

OperatorDefinition with basic operators
Intersection R∩SR \cap SR−(R−S)R - (R - S)
Theta join R⋈θSR \bowtie_{\theta} Sσθ(R×S)\sigma_{\theta}(R \times S)
Equijointheta join whose θ\theta is a conjunction of equalities
Natural join R⋈SR \bowtie Sequality on all common attribute names, then one copy of each common attribute kept
Division R÷SR \div S, R(X,Y)R(X, Y), S(Y)S(Y)πX(R)−πX((πX(R)×S)−R)\pi_X(R) - \pi_X\big((\pi_X(R) \times S) - R\big)
Assignment T←ET \leftarrow Enames an intermediate result

Outer joins

A natural or theta join drops a tuple that has no partner (a dangling tuple). Outer joins keep them, padding the missing attributes with NULL. The three outer joins are written as R] ⁣⋈SR \mathbin{]\!\bowtie} S (left), R⋈ ⁣[SR \mathbin{\bowtie\![} S (right) and R] ⁣⋈ ⁣[SR \mathbin{]\!\bowtie\![} S (full): the bracket marks the side whose dangling tuples are kept. Textbooks draw the same operators as a bowtie with extended horizontal strokes on the kept side.

  • Left outer join R] ⁣⋈SR \mathbin{]\!\bowtie} S: all of R⋈SR \bowtie S plus each dangling tuple of RR padded with NULLs.
  • Right outer join R⋈ ⁣[SR \mathbin{\bowtie\![} S: plus each dangling tuple of SS.
  • Full outer join R] ⁣⋈ ⁣[SR \mathbin{]\!\bowtie\![} S: plus dangling tuples of both.

In an ordinary equality/natural join, NULL equality is not TRUE, so NULL join keys do not match even each other. This does not apply to every theta predicate: IS NULL, null-safe equality or a TRUE OR branch can permit a match; evaluate the specified predicate.

How it works: the joins on one pair of tables

Take R(A,B)={(1,a),(2,b),(3,a),(4,c)}R(A, B) = \{(1, a), (2, b), (3, a), (4, c)\} and S(B,C)={(a,x),(a,y),(b,x),(d,z)}S(B, C) = \{(a, x), (a, y), (b, x), (d, z)\}.

Tables R(A, B) and S(B, C) and the results of their natural join (5 tuples), left outer join (6 tuples, adding 4, c, NULL), right outer join (6 tuples, adding NULL, d, z) and full outer join (7 tuples)
Figure 1. Natural, left outer, right outer and full outer join of the same two tables; dangling tuples are padded with NULL.
  • R×SR \times S has 4×4=164 \times 4 = 16 tuples and attributes A,R.B,S.B,CA, R.B, S.B, C.
  • R⋈SR \bowtie S matches on BB: (1,a,x),(1,a,y),(3,a,x),(3,a,y),(2,b,x)(1, a, x), (1, a, y), (3, a, x), (3, a, y), (2, b, x): 5 tuples.
  • R] ⁣⋈SR \mathbin{]\!\bowtie} S adds (4,c,NULL)(4, c, \text{NULL}): 6 tuples. R⋈ ⁣[SR \mathbin{\bowtie\![} S adds (NULL,d,z)(\text{NULL}, d, z): 6 tuples. R] ⁣⋈ ⁣[SR \mathbin{]\!\bowtie\![} S: 7 tuples.
  • πB(R)={a,b,c}\pi_B(R) = \{a, b, c\}: 3 tuples, not 4, because the two aa values merge.

Algorithms and pseudocode

Division answers "which xx are related to every yy in SS". The textbook expression works in three steps:

Text
DIVIDE(R(X, Y), S(Y))
  T1 <- pi_X(R)                  // every candidate x
  T2 <- (T1 x S) - R             // pairs (x, y) that WOULD be needed but are missing
  T3 <- pi_X(T2)                 // x values missing at least one y
  return T1 - T3

A direct evaluation sorts or hashes RR by XX and counts, for each xx, how many distinct yy of SS it has; xx qualifies when the count equals ∣S∣|S|. After hashing SS for expected O(1)O(1) membership tests, sorting RR gives expected O(∣S∣+∣R∣lg⁡∣R∣)O(|S|+|R|\lg|R|) time; sorting both inputs requires accounting for both sorting costs.

Nested-loop evaluation of R⋈θSR \bowtie_\theta S costs ∣R∣⋅∣S∣|R| \cdot |S| predicate tests; hash join on an equality costs O(∣R∣+∣S∣+output)O(|R| + |S| + \text{output}) on average.

Mathematical explanation

Cardinality bounds for ∣R∣=m|R| = m, ∣S∣=n|S| = n, both non-empty:

ExpressionMinimumMaximum
σp(R)\sigma_p(R)0mm
πL(R)\pi_L(R)1mm
R∪SR \cup Smax⁡(m,n)\max(m, n)m+nm + n
R∩SR \cap S0min⁡(m,n)\min(m, n)
R−SR - Smax⁡(0,m−n)\max(0, m - n)mm
R×SR \times Smnm nmnm n
R⋈SR \bowtie S0mnm n
R⋈θSR \bowtie_\theta S0mnm n
R⋈SR \bowtie S, common attributes a key of SS0mm
R] ⁣⋈SR \mathbin{]\!\bowtie} Smmmnm n
R⋈ ⁣[SR \mathbin{\bowtie\![} Snnmnm n
R] ⁣⋈ ⁣[SR \mathbin{]\!\bowtie\![} Smax⁡(m,n)\max(m, n)max⁡(mn,m+n)\max(m n, m + n)
R(X,Y)÷S(Y)R(X, Y) \div S(Y)0⌊m/n⌋\lfloor m / n \rfloor

Join with a foreign key. If the common attributes of RR and SS form a foreign key of RR, declared NOT NULL and referencing the primary key of SS, then every tuple of RR matches exactly one tuple of SS and ∣R⋈S∣=∣R∣|R \bowtie S| = |R|.

Where the outer-join bounds come from. Write j=∣R⋈S∣j = |R \bowtie S|, dRd_R and dSd_S for the numbers of dangling tuples. Then ∣R] ⁣⋈ ⁣[S∣=j+dR+dS|R \mathbin{]\!\bowtie\![} S| = j + d_R + d_S.

  • Maximum: either everything matches everything (j=mnj = m n, nothing dangles) or nothing matches (j=0j = 0, all m+nm + n tuples dangle). The larger wins, so for m=n=1m = n = 1 the maximum is 2, not 1.
  • Minimum: every tuple of either side appears in at least one output tuple, so the result has at least max⁡(m,n)\max(m, n) tuples; this is reached when each tuple of the smaller side matches exactly one tuple of the larger and the rest of the larger side dangles. For two 4-tuple relations, as in Figure 1, the full outer join has between 4 and 16 tuples; Figure 1 has 7.
  • If the common attributes are a key of SS, each RR tuple matches at most one SS tuple, so the inner join has at most mm tuples; the minimum 0 needs only that no value matches.

Natural join special cases. With no common attributes, R⋈S=R×SR \bowtie S = R \times S. With identical schemas, R⋈S=R∩SR \bowtie S = R \cap S. Always R⋈R=RR \bowtie R = R.

Why the division formula is right. xx is in the result iff (x,y)∈R(x, y) \in R for every y∈Sy \in S. πX(R)×S\pi_X(R) \times S lists every pair that would be required; subtracting RR leaves exactly the required-but-missing pairs; their xx values are the ones that fail, and removing them from the candidates leaves the answer. If SS is empty, nothing is required, nothing fails, and R÷S=πX(R)R \div S = \pi_X(R).

Worked examples

Example 1: division. Enrolled(sid, cid) = {(s1,c1),(s1,c2),(s1,c3),(s2,c1),(s2,c3),(s3,c2),(s3,c3),(s4,c1),(s4,c2),(s4,c3)}\{(s_1, c_1), (s_1, c_2), (s_1, c_3), (s_2, c_1), (s_2, c_3), (s_3, c_2), (s_3, c_3), (s_4, c_1), (s_4, c_2), (s_4, c_3)\}.

  • Divided by Req(cid) = {c1,c3}\{c_1, c_3\}: {s1,s2,s4}\{s_1, s_2, s_4\}. Here T2={(s3,c1)}T_2 = \{(s_3, c_1)\}, so T3={s3}T_3 = \{s_3\}.
  • Divided by {c1,c2,c3}\{c_1, c_2, c_3\}: {s1,s4}\{s_1, s_4\}.
  • Divided by the empty relation: {s1,s2,s3,s4}\{s_1, s_2, s_3, s_4\}.
The relation Enrolled with 10 tuples divided by Req containing c1 and c3: the intermediate pi_sid(Enrolled) x Req minus Enrolled leaves s3 with c1, so the result is s1, s2 and s4
Figure 2. Division step by step: the only required pair missing from Enrolled is (s3,c1)(s_3, c_1), so the result is {s1,s2,s4}\{s_1, s_2, s_4\}.

Example 2: maximum without aggregation. For R(A)={3,7,5}R(A) = \{3, 7, 5\}, the largest value is

πA(R)−πR.A(σR.A<T.A(R×ρT(R)))\pi_A(R) - \pi_{R.A}\big(\sigma_{R.A < T.A}(R \times \rho_T(R))\big)

The subtracted part is every value smaller than some other value, {3,5}\{3, 5\}, so the result is {7}\{7\}.

Example 3: "at least two courses". πE1.sid(σE1.sid=E2.sid∧E1.cid≠E2.cid(ρE1(Enrolled)×ρE2(Enrolled)))\pi_{E_1.sid}\big(\sigma_{E_1.sid = E_2.sid \wedge E_1.cid \neq E_2.cid}(\rho_{E_1}(\text{Enrolled}) \times \rho_{E_2}(\text{Enrolled}))\big) on the Enrolled relation of Example 1 returns all four students; "exactly one course" would be πsid(Enrolled)\pi_{sid}(\text{Enrolled}) minus that result, which is empty here.

Example 4: projection then selection order. πA(σB=a(R))={1,3}\pi_A(\sigma_{B = a}(R)) = \{1, 3\} on the RR of Figure 1, but σB=a(πA(R))\sigma_{B = a}(\pi_A(R)) is not even well formed: BB was projected away. Selection and projection commute only when the projection keeps every attribute that the predicate uses.

Example 5: join with a foreign key. EMP(eno, dno) with 5 rows and dno a NOT NULL foreign key to DEPT(dno, dname) with 3 rows: ∣EMP⋈DEPT∣=5|EMP \bowtie DEPT| = 5 whatever the data. If 2 employees had dno NULL instead, the natural join would have 3 tuples and the left outer join 5.

Important properties and observations

  • Set semantics. Projection and union remove duplicates; ∣πL(R)∣|\pi_L(R)| can be less than ∣R∣|R| unless LL contains a key.
  • Selections cascade and commute: σp∧q(R)=σp(σq(R))=σq(σp(R))\sigma_{p \wedge q}(R) = \sigma_p(\sigma_q(R)) = \sigma_q(\sigma_p(R)).
  • Projections cascade: πL1(πL2(R))=πL1(R)\pi_{L_1}(\pi_{L_2}(R)) = \pi_{L_1}(R) when L1⊆L2L_1 \subseteq L_2.
  • Selection distributes over ∪\cup, ∩\cap and −-; projection distributes over ∪\cup but not over ∩\cap or −-. Example: R={(1,a)}R = \{(1, a)\}, S={(1,b)}S = \{(1, b)\}: π1(R∩S)=∅\pi_1(R \cap S) = \emptyset but π1(R)∩π1(S)={1}\pi_1(R) \cap \pi_1(S) = \{1\}.
  • Natural inner joins are commutative and associative (up to attribute order); theta joins require correctly reassociated predicates, and outer joins are excluded; ×\times and ⋈\bowtie are the expensive operators, so optimisers push selections below them.
  • Difference is not commutative; R−SR - S and S−RS - R differ in general.
  • Mixing inner and outer joins is not associative: (R] ⁣⋈S)⋈T(R \mathbin{]\!\bowtie} S) \bowtie T can differ from R] ⁣⋈(S⋈T)R \mathbin{]\!\bowtie} (S \bowtie T). A selection on an attribute of the padded side also cannot be pushed below an outer join: σC=x(R] ⁣⋈S)\sigma_{C = x}(R \mathbin{]\!\bowtie} S) on Figure 1 has 3 tuples, R] ⁣⋈σC=x(S)R \mathbin{]\!\bowtie} \sigma_{C = x}(S) has 4.

Related material. Aggregation and grouping GγF(R)_{G}\gamma_{F}(R), duplicate elimination and sorting belong to the extended algebra used for SQL; the GATE syllabus algebra is the set-based core above. Semi-join R⋉S=πR(R⋈S)R \ltimes S = \pi_{R}(R \bowtie S) appears in distributed query processing.

Common misconceptions.

  • "∣R⋈S∣≤max⁡(∣R∣,∣S∣)|R \bowtie S| \leq \max(|R|, |S|)." No: up to ∣R∣⋅∣S∣|R| \cdot |S|, when every tuple matches every tuple.
  • "R÷SR \div S is empty when SS is empty." No: it is πX(R)\pi_X(R).
  • "Natural join compares NULLs as equal." It does not; NULL never satisfies an equality.

GATE examination perspective

  • Evaluate an expression. Work on small tables: track duplicates removed by projection and NULL padding of outer joins.
  • Cardinality questions. Minimum and maximum tuples of a join, union or difference; joins on a foreign key.
  • "For all" queries. These are division; recognise the π−π((π×S)−R)\pi - \pi((\pi \times S) - R) shape even when written without ÷\div.
  • Equivalence of expressions. Which rewrites (pushing selection, distributing projection) are valid.
  • Self-joins with rename. Apply this to "at least two", "maximum" and "pairs" queries.

Summary

Sources

  1. A. Silberschatz, H. F. Korth, S. Sudarshan, Database System Concepts, 7th ed., McGraw-Hill, 2019 (2020 copyright), 2.6 The Relational Algebra; Chapter 27 Formal Relational Query Languages.
  2. R. Elmasri, S. B. Navathe, Fundamentals of Database Systems, 7th ed., Pearson, 8.1 Unary Relational Operations: SELECT and PROJECT; 8.2 Relational Algebra Operations from Set Theory; 8.3 Binary Relational Operations: JOIN and DIVISION; 8.4 Additional Relational Operations.

Next steps