Structured Query Language (SQL) is the declarative domain-specific language for defining, querying, and manipulating data residing in relational database management systems (RDBMS). Introduced in 1970 by mathematician Edgar F. Codd, relational theory models data as mathematical Relations (tables), which are sets of unordered Tuples (rows) conforming to defined Attributes (columns).
A relational database engine translates declarative SQL text into formal Relational Algebra Trees:
Selection (σϕ): Filters tuples satisfying a propositional formula ϕ (WHERE clause).
Projection (πA1,…,An): Slices relations into a specified subset of attributes (SELECT clause).
Cartesian Product (R×S): Generates all pairwise tuple combinations from relations R and S.
Theta-Join (R⋈θS): Combines Cartesian product with an attribute condition θ (ON / JOIN).
Set Operations (∪,∩,− ): UNION, INTERSECT, and EXCEPT (preserves relational set theory).
flowchart TD
subgraph DeclarativeToAlgebra["Declarative SQL Compilation to Relational Algebra"]
SQLText["Declarative SQL: SELECT name, email FROM users WHERE active = true"] --> AST["SQL Parser & Abstract Syntax Tree"]
AST --> RelAlg["Relational Algebra: π_{name, email}(σ_{active = true}(Users))"]
RelAlg --> CBO["Cost-Based Optimizer (CBO)"]
CBO --> PhysicalPlan["Physical Execution: Index Scan on idx_users_active -> Project"]
end
2. Logical Query Processing Order
Unlike imperative programming languages that execute statements top-to-bottom, a relational query engine processes clauses in a mathematically mandated logical order:
1. FROM→2. ON→3. JOIN→4. WHERE→5. GROUP BY→6. HAVING→7. SELECT→8. DISTINCT→9. ORDER BY→10. LIMIT / OFFSET
flowchart TD
F["1. FROM (Identifies source tables & virtual tables)"] --> ON_CL["2. ON (Evaluates join predicates)"]
ON_CL --> J["3. JOIN (Produces joined intermediate relation)"]
J --> W["4. WHERE (Filters rows prior to aggregation)"]
W --> G["5. GROUP BY (Partitions rows into group buckets)"]
G --> H["6. HAVING (Filters group buckets based on aggregate conditions)"]
H --> S["7. SELECT (Computes scalar expressions & column projections)"]
S --> D["8. DISTINCT (Eliminates duplicate output rows)"]
D --> O["9. ORDER BY (Sorts result set)"]
O --> L["10. LIMIT / OFFSET (Slices final output window)"]
NOTE
Because WHERE (Step 4) executes beforeSELECT (Step 7), column aliases declared in the SELECT list cannot be referenced within the WHERE clause.
3. Data Definition Language (DDL) & Constraint Mechanics
DDL defines and modifies the physical and logical structure of database relations. Relational integrity is enforced through schema-level Integrity Constraints:
flowchart LR
subgraph LogicalJoins["Logical Join Types"]
Inner["INNER JOIN: Intersection (∩)"]
Left["LEFT JOIN: All Left + Matching Right"]
Right["RIGHT JOIN: All Right + Matching Left"]
Full["FULL OUTER JOIN: Union of all rows"]
Cross["CROSS JOIN: Cartesian Product (M × N)"]
end
4.1 Physical Join Algorithms in Database Engines
flowchart TD
AlgChoice["Optimizer Physical Join Selection"]
AlgChoice --> NL["1. Nested Loop Join<br/>- For each outer tuple, scan inner index<br/>- O(M * log N) time; O(1) RAM"]
AlgChoice --> HJ["2. Hash Join<br/>- Build hash table for smaller table in work_mem<br/>- O(M + N) time; High memory demand"]
AlgChoice --> MJ["3. Sort-Merge Join<br/>- Both relations pre-sorted by join key<br/>- O(M + N) stream scan; Zero disk spill"]
In relational database theory, NULL represents the absence of a value or an unknown state, not zero or an empty string. Consequently, boolean logic in SQL evaluates to TRUE, FALSE, or UNKNOWN.
5.1 3VL Truth Tables
Operator
Left Operand
Right Operand
Result
=
NULL
NULL
UNKNOWN (Evaluates to FALSE in WHERE!)
!=
42
NULL
UNKNOWN
AND
TRUE
UNKNOWN
UNKNOWN
AND
FALSE
UNKNOWN
FALSE
OR
TRUE
UNKNOWN
TRUE
OR
FALSE
UNKNOWN
UNKNOWN
NOT
UNKNOWN
—
UNKNOWN
IMPORTANT
Because NULL = NULL yields UNKNOWN, SQL statements filtering on nullable columns must use IS NULL, IS NOT NULL, or the null-safe comparison IS DISTINCT FROM:
-- Correct Null-Safe Equality check in PostgreSQLSELECT * FROM products WHERE discount IS DISTINCT FROM 0.00;
6. Subqueries vs. Joins: Semi-Joins & Anti-Joins
flowchart TD
subgraph SemiAntiJoin["Semi-Join vs Anti-Join Mechanics"]
Semi["Semi-Join (⋉ / EXISTS)<br/>- Returns left rows having AT LEAST ONE match in right table<br/>- Short-circuits on first match!"]
Anti["Anti-Join (&rhd; / NOT EXISTS)<br/>- Returns left rows having ZERO matches in right table"]
end
6.1 The Dangerous NOT IN with Nullable Columns Trap
-- DANGEROUS BUG: If ANY row in inactive_users has NULL id, this query returns ZERO rows!SELECT * FROM users WHERE id NOT IN (SELECT user_id FROM inactive_users);-- PRODUCTION STANDARD: Hash Anti-Join via NOT EXISTS (Safe against NULLs)SELECT u.*FROM users u WHERE NOT EXISTS ( SELECT 1 FROM inactive_users iu WHERE iu.user_id = u.id);