Loading content...
In the 1970s, while IBM was developing SQL as a text-based query language, another approach emerged from the same research labs—one that would prove equally influential in shaping how humans interact with databases.
Query-by-Example (QBE), invented by Moshe Zloof at IBM Research in 1975, proposed a radical idea: instead of writing textual queries, users could simply fill in table templates with example values and conditions. Behind this intuitive interface lay the theoretical foundation of Domain Relational Calculus.
Understanding the deep connection between DRC and QBE reveals how abstract mathematical formalisms become practical, user-friendly tools. It also illuminates why certain interface patterns feel natural—they're grounded in solid theoretical foundations.
By the end of this page, you will understand QBE's historical context and significance, master QBE syntax and semantics, translate between QBE and DRC representations, and appreciate QBE's lasting influence on modern database interfaces and tools.
The Setting:
The early 1970s were a transformative period for database technology. E.F. Codd had published his seminal work on the relational model (1970), and IBM research was exploring how to make this theoretical model accessible to users.
Two parallel efforts emerged:
SEQUEL (later SQL) — A textual language emphasizing English-like syntax, developed by Chamberlin and Boyce. Influenced by TRC.
Query-by-Example (QBE) — A visual, tabular language where users interact with table skeletons, developed by Moshe Zloof. Influenced by DRC.
Moshe Zloof's Insight:
Zloof realized that non-programmer users struggled with textual query languages. Even SQL, designed to be "English-like," required learning specific keywords, syntax rules, and logical operators.
His key insight: Why not let users query by showing examples of what they want? Instead of describing results in words, users could demonstrate results by filling in sample values.
| Aspect | SQL (TRC-inspired) | QBE (DRC-inspired) |
|---|---|---|
| Paradigm | Textual/Linear | Visual/Tabular |
| Abstraction | Tuple (row) oriented | Value (cell) oriented |
| User action | Write statements | Fill in templates |
| Learning curve | Syntax mastery required | "Show by example" |
| Target users | Programmers, analysts | End users, casual queriers |
| Condition expression | WHERE clause | Cell entries |
| Join expression | ON/WHERE equality | Shared example elements |
QBE's Publication and Impact:
QBE was first presented in 1975 and formally published in 1977. It received immediate recognition:
Though SQL eventually became the standard for programmatic access, QBE's ideas permeate every modern database admin tool with visual query builders.
SQL and QBE are both relationally complete—anything expressible in one can be expressed in the other. They differ not in power but in interface paradigm. SQL suits automation and programmers; QBE suits exploration and non-programmers. Both remain relevant today.
QBE presents queries as annotated table skeletons. Users see empty tables corresponding to database relations and fill in cells with:
Basic Structure:
QBE TABLE SKELETON COMPONENTS═════════════════════════════ ┌─────────────────────────────────────────────────────────────┐│ TableName │ Column1 │ Column2 │ Column3 │ ... │├─────────────────────────────────────────────────────────────┤│ │ │ │ │ ││ entries │ entries │ entries │ entries │ ... ││ │ │ │ │ │└─────────────────────────────────────────────────────────────┘ ENTRY TYPES:─────────────_x, _y, _name → Example elements (like DRC domain variables)'Alice', 2024 → Constants (literal values)>50000, ≤100 → Conditions (comparisons)P. → Print command (include in output)P._x → Print and use as example elementI. → Insert commandD. → Delete commandU. → Update command_x = _y + 10 → Computed valueAO. (DO.) → Ascending/Descending order EXAMPLE:────────┌──────────┬──────────┬──────────┬──────────┬──────────┐│ Employee │ EmpID │ Name │ Salary │ DeptID │├──────────┼──────────┼──────────┼──────────┼──────────┤│ │ │ P._n │ >50000 │ │└──────────┴──────────┴──────────┴──────────┴──────────┘ Meaning: Print names of employees with salary over 50000Example Elements — The Heart of QBE:
Example elements (like _name, _x, _sal) serve the same role as domain variables in DRC:
The "Query-by-Example" Philosophy:
The name reflects the approach: you provide examples of what you want. If you want employee names, you say "give me _name" by putting P._name in the Name column. If you want high earners, you put ">50000" in the Salary column. The system matches these examples against the actual data.
Think of QBE as filling out a form describing what you want. Each cell either constrains ('only rows where this column satisfies this condition') or requests ('include this column in results'). The table structure mirrors the database, making navigation intuitive.
Let's see QBE in action with progressively complex queries, comparing each to its DRC equivalent.
Example 3.1: Simple Selection and Projection
Find names and salaries of employees earning over $50,000.
QBE:┌──────────┬──────────┬──────────┬──────────┬──────────┐│ Employee │ EmpID │ Name │ Salary │ DeptID │├──────────┼──────────┼──────────┼──────────┼──────────┤│ │ │ P._n │ P.>50000 │ │└──────────┴──────────┴──────────┴──────────┴──────────┘ Reading:• P._n in Name → Print the name (output this column)• P.>50000 in Salary → Print salary AND it must be > 50000• Empty cells → No constraint or output for those columns DRC Equivalent:{ <n, s> | ∃e ∃d (Employee(e, n, s, d) ∧ s > 50000) } Correspondence:• P._n matches free variable n in target <n, s>• P.>50000 matches free variable s with condition s > 50000• Empty EmpID, DeptID match existentially quantified e, dExample 3.2: Join Query
Find employee names with their department names.
QBE (Two tables):┌──────────┬──────────┬──────────┬──────────┬──────────┐│ Employee │ EmpID │ Name │ Salary │ DeptID │├──────────┼──────────┼──────────┼──────────┼──────────┤│ │ │ P._n │ │ _d │└──────────┴──────────┴──────────┴──────────┴──────────┘ ┌────────────┬──────────┬──────────┬───────────┐│ Department │ DeptID │ DeptName │ ManagerID │├────────────┼──────────┼──────────┼───────────┤│ │ _d │ P._dn │ │└────────────┴──────────┴──────────┴───────────┘ Reading:• _d appears in BOTH tables' DeptID column → JOIN condition!• P._n in Employee.Name → Print employee names• P._dn in Department.DeptName → Print department names DRC Equivalent:{ <n, dn> | ∃e ∃s ∃d ∃m (Employee(e, n, s, d) ∧ Department(d, dn, m)) } The shared example element _d perfectly maps to the shared variable d in DRC that implements the natural join.Example 3.3: Negation (NOT EXISTS)
Find employees who are not in the Engineering department.
QBE:┌──────────┬──────────┬──────────┬──────────┬──────────┐│ Employee │ EmpID │ Name │ Salary │ DeptID │├──────────┼──────────┼──────────┼──────────┼──────────┤│ │ │ P._n │ │ _d │└──────────┴──────────┴──────────┴──────────┴──────────┘ ┌────────────┬──────────┬──────────────────┬───────────┐│ Department │ DeptID │ DeptName │ ManagerID │├────────────┼──────────┼──────────────────┼───────────┤│ ¬ │ _d │ Engineering │ │└────────────┴──────────┴──────────────────┴───────────┘ Reading:• ¬ in the table row prefix means "NOT EXISTS"• This row must NOT exist in Department• Effect: Employee's dept ≠ Engineering DRC Equivalent:{ <n> | ∃e ∃s ∃d (Employee(e, n, s, d) ∧ ¬∃m (Department(d, 'Engineering', m))) } The ¬ prefix in QBE directly corresponds to the negated existential ¬∃ in DRC.The beauty of QBE shines in joins: simply use the same example element in columns that should match. No need to write 'ON Employee.DeptID = Department.DeptID'—the visual repetition of _d says it all. This directly mirrors DRC's variable sharing for joins.
The structural similarity between QBE and DRC enables systematic translation. Understanding this translation illuminates both formalisms.
QBE to DRC Translation Algorithm:
QBE TO DRC TRANSLATION══════════════════════ Step 1: Create Target List───────────────────────────• For each cell with P._x, add x to target list: <x₁, x₂, ...>• For each cell with P.constant, create fresh variable in target Step 2: Create Membership Predicates─────────────────────────────────────• For each table row, create: TableName(var₁, var₂, ..., varₙ)• Position i gets variable from that column's example element• If column has constant, use constant• If column is empty, create fresh existentially quantified variable Step 3: Create Conditions─────────────────────────• For each cell with condition like >50000: Add: variable > 50000 to formula• For each cell with condition like ≠'HR': Add: variable ≠ 'HR' to formula Step 4: Handle Negation───────────────────────• For rows prefixed with ¬: Wrap entire row predicate with ¬∃(...) Step 5: Combine with Conjunctions─────────────────────────────────• Join all predicates and conditions with ∧ Step 6: Add Quantifiers───────────────────────• Variables in target list: FREE• Other variables: Existentially quantified (∃)• Negated row variables: Within negated scopeDetailed Translation Example:
QBE Query: Find names & salaries where salary > GPA * 10000 ┌─────────┬─────┬──────────┬─────────┬──────────────┐│ Student │ SID │ Name │ GPA │ AdvisorID │├─────────┼─────┼──────────┼─────────┼──────────────┤│ │ _s │ P._n │ _g │ │└─────────┴─────┴──────────┴─────────┴──────────────┘ ┌──────────┬─────┬──────────┬── ─────────────────┬──────────┐│ PartTime │ SID │ Salary │ Salary Condition │ Hours │├──────────┼─────┼──────────┼───────────────────-┼──────────┤│ │ _s │ P._sal │ > _g * 10000 │ │└──────────┴─────┴──────────┴────────────────────┴──────────┘ Translation: Step 1: Target list from P. cells → <n, sal> Step 2: Membership predicates Student: Student(_s, _n, _g, _a) -- _a fresh for empty AdvisorID PartTime: PartTime(_s, _sal, _h) -- _h fresh for empty Hours Step 3: Conditions → sal > g * 10000 Step 4: No negation rows Step 5: Combine Student(_s, _n, _g, _a) ∧ PartTime(_s, _sal, _h) ∧ sal > g * 10000 Step 6: Quantifiers Free: n, sal Bound: s, g, a, h FINAL DRC:{ <n, sal> | ∃s ∃g ∃a ∃h ( Student(s, n, g, a) ∧ PartTime(s, sal, h) ∧ sal > g * 10000) }Every well-formed QBE query has a corresponding DRC expression, and vice versa. The translation preserves semantics perfectly. This isn't coincidence—QBE was explicitly designed with DRC as its formal foundation.
QBE extended beyond basic DRC to include features for practical database manipulation:
1. Aggregation Functions
QBE supports aggregate operations not present in basic DRC:
Aggregation in QBE:┌──────────┬──────────┬──────────┬────────────┐│ Employee │ DeptID │ Name │ Salary │├──────────┼──────────┼──────────┼────────────┤│ │ P._d │ │ P.AVG._sal │└──────────┴──────────┴──────────┴────────────┘ Meaning: For each department, print average salary Built-in aggregates:• CNT. (count)• SUM. (sum)• AVG. (average)• MAX. (maximum)• MIN. (minimum)• UN.ALL (with duplicates)2. Grouping (G.)
The G. operator groups results for aggregation:
Grouping in QBE:┌──────────┬──────────┬──────────┬────────────┐│ Employee │ DeptID │ Name │ Salary │├──────────┼──────────┼──────────┼────────────┤│ │ P.G._d │ │ P.SUM._sal │└──────────┴──────────┴──────────┴────────────┘ Meaning: Group by department, sum salaries in each group SQL Equivalent:SELECT DeptID, SUM(Salary) FROM Employee GROUP BY DeptID3. Update Operations (I., D., U.)
QBE supports data modification:
INSERT:┌──────────┬──────────┬──────────┬──────────┐│ Employee │ EmpID │ Name │ Salary │├──────────┼──────────┼──────────┼──────────┤│ I. │ E999 │ 'New' │ 50000 │└──────────┴──────────┴──────────┴──────────┘ DELETE:┌──────────┬──────────┬──────────┬──────────┐│ Employee │ EmpID │ Name │ Salary │├──────────┼──────────┼──────────┼──────────┤│ D. │ │ │ <30000 │└──────────┴──────────┴──────────┴──────────┘(Delete employees earning less than 30000) UPDATE:┌──────────┬──────────┬──────────┬────────────────┐│ Employee │ EmpID │ Name │ Salary │├──────────┼──────────┼──────────┼────────────────┤│ U. │ │ │ _sal * 1.10 ││ │ │ │ (_sal) │└──────────┴──────────┴──────────┴────────────────┘(10% raise for all — update current _sal to _sal * 1.10)4. Universal Quantification (ALL.)
QBE provides syntax for "for all" queries, corresponding to DRC's ∀:
Find students enrolled in ALL Computer Science courses: ┌─────────┬──────────┬──────────┬─────────┐│ Student │ SID │ Name │ Major │├─────────┼──────────┼──────────┼─────────┤│ │ _s │ P._n │ │└─────────┴──────────┴──────────┴─────────┘ ┌────────┬──────────┬──────────┬──────────┐│ Course │ CourseID │ Title │ Dept │├────────┼──────────┼──────────┼──────────┤│ ALL. │ _c │ │ CS │└────────┴──────────┴──────────┴──────────┘ ┌────────────┬──────────┬──────────┬──────────┐│ Enrollment │ SID │ CourseID │ Grade │├────────────┼──────────┼──────────┼──────────┤│ │ _s │ _c │ │└────────────┴──────────┴──────────┴──────────┘ The ALL. prefix on Course indicates: "for all courses matchingthis row's conditions, there must be a corresponding Enrollment."QBE's aggregation and grouping features extend beyond what basic DRC can express. These additions made QBE practical for real data analysis tasks. Modern visual query builders inherit these extensions while maintaining QBE's intuitive tabular paradigm.
QBE's impact extends far beyond its original implementation. Its ideas permeate modern database interfaces:
1. Microsoft Access Query Designer
Perhaps the most direct descendant of QBE, Access's visual query designer:
2. phpMyAdmin & Database Admin Tools
Web-based database interfaces incorporate QBE concepts:
| Tool/Interface | QBE Feature Inherited | Implementation |
|---|---|---|
| Microsoft Access | Full QBE grid | Native design view |
| LibreOffice Base | Query designer | Visual SELECT builder |
| MySQL Workbench | Visual query builder | Drag-drop tables, click fields |
| pgAdmin (PostgreSQL) | Query tool | Visual query builder option |
| DataGrip (JetBrains) | Database explorer | Click-to-filter, visual joins |
| Airtable/Notion | Filter interfaces | Column-based filter UI |
| Excel/Sheets filters | AutoFilter | Value-in-column filtering |
| Tableau/Power BI | Drag-drop querying | Visual dimension/measure selection |
3. Low-Code/No-Code Platforms
Modern low-code platforms embrace QBE's "show by example" philosophy:
4. Natural Language Interfaces
Emerging NL-to-SQL systems often produce intermediate representations similar to QBE:
The Lasting Legacy:
QBE proved that database querying need not be a textual, programming-oriented activity. By providing a visual paradigm grounded in solid theory (DRC), it opened databases to non-programmers and established interface patterns still dominant today.
QBE beautifully demonstrates how theoretical formalisms (DRC) can inspire practical, user-friendly tools. The value-oriented thinking of DRC—where each cell is a separate variable—maps perfectly to spreadsheet-like interfaces where users think in terms of column values.
Let's bring together SQL, QBE, and DRC to see the same queries expressed in all three forms. This triangulation reinforces understanding of each.
Example: Complex Join with Condition
Find names and departments of employees earning over $60,000 who work in departments with budget over $1,000,000.
SQL:─────SELECT e.Name, d.DeptNameFROM Employee eJOIN Department d ON e.DeptID = d.DeptIDWHERE e.Salary > 60000 AND d.Budget > 1000000 QBE:────┌──────────┬──────────┬──────────┬──────────┬──────────┐│ Employee │ EmpID │ Name │ Salary │ DeptID │├──────────┼──────────┼──────────┼──────────┼──────────┤│ │ │ P._n │ >60000 │ _d │└──────────┴──────────┴──────────┴──────────┴──────────┘ ┌────────────┬──────────┬──────────────┬───────────┬───────────────┐│ Department │ DeptID │ DeptName │ ManagerID │ Budget │├────────────┼──────────┼──────────────┼───────────┼───────────────┤│ │ _d │ P._dn │ │ >1000000 │└────────────┴──────────┴──────────────┴───────────┴───────────────┘ DRC:────{ <n, dn> | ∃e ∃s ∃d ∃m ∃b ( Employee(e, n, s, d) ∧ s > 60000 ∧ Department(d, dn, m, b) ∧ b > 1000000) } CORRESPONDENCE MATRIX:━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Component │ SQL │ QBE │ DRC━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Output columns │ SELECT │ P. │ Target list Table sources │ FROM/JOIN │ Tables │ Membership Join condition │ ON │ Shared │ Shared var Selection │ WHERE │ Cell │ Condition━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━Example: Negation with Universal Quantification
Find employees who have worked on every project in their department.
SQL:─────SELECT e.NameFROM Employee eWHERE NOT EXISTS ( SELECT 1 FROM Project p WHERE p.DeptID = e.DeptID AND NOT EXISTS ( SELECT 1 FROM Assignment a WHERE a.EmpID = e.EmpID AND a.ProjectID = p.ProjectID )) QBE (using negation):─────────────────────┌──────────┬──────────┬──────────┬──────────┐│ Employee │ EmpID │ Name │ DeptID │├──────────┼──────────┼──────────┼──────────┤│ │ _e │ P._n │ _d │└──────────┴──────────┴──────────┴──────────┘ ┌─────────┬───────────┬──────────┐│ Project │ ProjectID │ DeptID │├─────────┼───────────┼──────────┤│ ¬ │ _p │ _d │└─────────┴───────────┴──────────┘ ┌────────────┬──────────┬───────────┐│ Assignment │ EmpID │ ProjectID │├────────────┼──────────┼───────────┤│ ¬ │ _e │ _p │└────────────┴──────────┴───────────┘ (Nested negation: NOT EXISTS a project where NOT EXISTS assignment) DRC:────{ <n> | ∃e ∃d ( Employee(e, n, d) ∧ ¬∃p ( Project(p, d) ∧ ¬∃... (Assignment(e, p)) )) }All three representations express identical queries. SQL uses English-like keywords, QBE uses visual cell entries, and DRC uses logical symbols. Understanding all three develops flexible query thinking—you can choose the most natural representation for any given problem.
We've explored the deep connection between Query-by-Example and Domain Relational Calculus. Let's consolidate the key insights:
Module Conclusion:
This completes our exploration of Domain Relational Calculus. We've journeyed from domain variables through formal syntax, compared DRC with TRC, worked through comprehensive query examples, and connected DRC to its practical descendant QBE.
DRC offers a value-oriented perspective on declarative querying that complements TRC's tuple orientation. Together, they form the theoretical foundation for understanding all relational query languages—from SQL to visual query builders to emerging natural language interfaces.
With this knowledge, you now possess deep insight into the mathematics underlying database querying, enabling you to reason about query semantics at a fundamental level.
Congratulations! You've mastered Domain Relational Calculus—from its foundational domain variables to its manifestation in Query-by-Example. You understand both the theory (DRC syntax and semantics) and its practical impact (QBE and modern visual interfaces). This knowledge deepens your understanding of relational query languages at their mathematical core.