Relational algebra query patterns¶
TL;DR patterns¶
- Existential ("at least one"): join what you need, use \(\sigma\) to filter, then \(\pi\) to keep the id(s).
- Universal / "only" / "all": \(\text{result ids} = \text{candidates} - \text{intruders}\) (project ids before the difference).
- "At least k" matches: self-join \(k\) copies (or group if allowed), then require \(k\) distinct matches for the same id.
- Min / Max via self-join: keep rows not beaten by a strictly smaller/greater one using self-join plus difference.
Keyword guide¶
| Keyword | Quantifier | Core operator |
|---|---|---|
| "at least one", "some", "exists" | \(\exists\) | join + select \(\sigma\) |
| "only", "all", "every", "no" | \(\forall\) | difference (candidates \(-\) intruders) |
Existential (easy case)¶
Pattern: join what you need, filter, project ids.
Example: students who passed at least one CS exam.
Universal / "only" / "all" (complement trick)¶
Use candidates minus intruders. Always project to the same schema (usually ids) before the difference.
- \(CANDIDATES = \pi_{id}(\dots)\) (everyone who could qualify)
- \(INTRUDERS = \pi_{id}( \sigma_{\text{bad}}(\dots) )\)
- \(RESULT = CANDIDATES - INTRUDERS\)
Example: people who attended only foreign concerts.
Mental model: find violators (intruders) and subtract them from the candidates.
"At least k" occurrences¶
If grouping is unavailable, self-join k distinct occurrences and force them to be different.
Example: customers who bought at least 2 distinct items (Order(cust, item)).
For k=3, chain three renamings and pairwise item inequalities; project one cust.
Min / Max with self-join¶
Given \(R(\text{id}, \text{val})\), keep rows that are not beaten by a strictly better competitor.
- Minimum(s): \(\large{MIN = R - \pi_{\text{r1.*}}\bigl( \sigma_{\text{r2.val} < \text{r1.val}}( \rho_1(R) \bowtie \rho_2(R) ) \bigr)}\)
- Maximum(s): replace \(<\) with \(>\).
This is the same anti-dominance trick: remove any row that has a strictly smaller (or larger) partner with the same comparison domain.
Quick checklist¶
- Before \(A - B\), ensure \(A\) and \(B\) have the same attributes (usually just the id).
- For "only/all", always project ids in both CANDIDATES and INTRUDERS.
- For self-join min/max, use strict inequality so ties survive (you keep all minima/maxima).
- Rename consistently when self-joining to avoid attribute clashes.