thecodex.expert · The Codex Family of Knowledge
SQL

SQL Querying

Describe what data you want. The database figures out how to get it — that's the power of declarative SQL.

ISO/IEC 9075 PostgreSQL 16 Last verified:
Canonical Definition

SQL querying uses the SELECT statement to describe which columns and rows to retrieve — WHERE filters rows, ORDER BY sorts results, LIMIT restricts output count, and CASE provides conditional expressions — all evaluated in a defined logical order: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT.

One sentence

SQL is declarative — you describe the data you want, and the database figures out the most efficient way to retrieve it. The SELECT statement is the core tool for every query.

SELECT basics

SQLselect.sql
-- Basic SELECT: choose which columns, from which table
SELECT name, department, salary
FROM   employees;

-- All columns (avoid in production code — fragile if schema changes)
SELECT * FROM employees;

-- Column aliases
SELECT
    name                       AS employee_name,
    salary                     AS annual_salary,
    salary / 12.0              AS monthly_salary,
    UPPER(department)          AS dept_upper
FROM employees;

-- DISTINCT — remove duplicate rows
SELECT DISTINCT department FROM employees;

-- LIMIT and OFFSET — pagination
SELECT name, salary
FROM   employees
ORDER  BY salary DESC
LIMIT  10 OFFSET 20;   -- rows 21-30

WHERE — filtering rows

SQLwhere.sql
-- Comparison operators
SELECT * FROM employees WHERE salary > 80000;
SELECT * FROM employees WHERE department = 'Engineering';
SELECT * FROM employees WHERE hire_date >= '2020-01-01';

-- Logical operators: AND, OR, NOT
SELECT * FROM employees
WHERE  department = 'Engineering'
AND    salary > 80000;

SELECT * FROM employees
WHERE  department = 'Engineering'
OR     department = 'Design';

-- IN — match any value in a list (cleaner than multiple OR)
SELECT * FROM employees
WHERE  department IN ('Engineering', 'Design', 'Product');

-- BETWEEN — inclusive range
SELECT * FROM employees
WHERE  salary BETWEEN 60000 AND 90000;

-- LIKE — pattern matching
-- % = zero or more characters,  _ = exactly one character
SELECT * FROM employees WHERE name LIKE 'P%';       -- starts with P
SELECT * FROM employees WHERE email LIKE '%@gmail.com';
SELECT * FROM employees WHERE name LIKE '_riya';    -- 5-letter names ending in "riya"

-- ILIKE — case-insensitive LIKE (PostgreSQL)
SELECT * FROM employees WHERE name ILIKE 'priya';

-- NULL checks — NEVER use = NULL
SELECT * FROM employees WHERE manager_id IS NULL;
SELECT * FROM employees WHERE phone IS NOT NULL;

ORDER BY and CASE

SQLorder_case.sql
-- ORDER BY — sort results
SELECT name, salary, department
FROM   employees
ORDER  BY salary DESC, name ASC;   -- salary descending, then name ascending

-- CASE — conditional expression (like if/else in SQL)
SELECT
    name,
    salary,
    CASE
        WHEN salary >= 100000 THEN 'Senior'
        WHEN salary >= 70000  THEN 'Mid-level'
        WHEN salary >= 50000  THEN 'Junior'
        ELSE                       'Entry'
    END AS level
FROM employees;

-- CASE in ORDER BY — custom sort order
SELECT name, status
FROM   orders
ORDER  BY
    CASE status
        WHEN 'urgent'   THEN 1
        WHEN 'pending'  THEN 2
        WHEN 'complete' THEN 3
        ELSE                 4
    END;

-- COALESCE — return first non-null value
SELECT
    name,
    COALESCE(phone, mobile, 'no contact') AS contact_number
FROM employees;

-- NULLIF — return NULL if two values are equal (prevents division by zero)
SELECT revenue / NULLIF(expenses, 0) AS ratio FROM financials;

Subqueries

SQLsubqueries.sql
-- Subquery in WHERE — scalar subquery returns one value
SELECT name, salary
FROM   employees
WHERE  salary > (SELECT AVG(salary) FROM employees);

-- Subquery in WHERE — returns a list (use with IN)
SELECT name FROM employees
WHERE  department_id IN (
    SELECT id FROM departments WHERE location = 'Mumbai'
);

-- Correlated subquery — references the outer query (runs once per row)
SELECT e.name, e.salary
FROM   employees e
WHERE  e.salary = (
    SELECT MAX(e2.salary)
    FROM   employees e2
    WHERE  e2.department = e.department
);
-- "Employees who earn the most in their department"

-- Subquery in FROM clause (derived table / inline view)
SELECT dept_name, avg_salary
FROM (
    SELECT   department AS dept_name,
             AVG(salary)  AS avg_salary
    FROM     employees
    GROUP BY department
) AS dept_stats
WHERE avg_salary > 75000;

-- EXISTS — check if any matching rows exist (often faster than IN)
SELECT name FROM employees e
WHERE EXISTS (
    SELECT 1 FROM projects p
    WHERE  p.lead_id = e.id
);

String and date functions

SQLfunctions.sql
-- String functions (PostgreSQL)
SELECT
    UPPER(name),                         -- PRIYA SHARMA
    LOWER(email),                        -- priya@example.com
    LENGTH(name),                        -- 11
    TRIM(BOTH ' ' FROM name),            -- strip whitespace
    SUBSTRING(name FROM 1 FOR 5),        -- first 5 chars
    POSITION('.' IN email),              -- find position
    REPLACE(phone, '-', ''),             -- remove dashes
    CONCAT(first_name, ' ', last_name),  -- or use || operator
    first_name || ' ' || last_name AS full_name
FROM employees;

-- Date functions
SELECT
    CURRENT_DATE,                        -- today
    CURRENT_TIMESTAMP,                   -- now with time zone
    hire_date + INTERVAL '30 days',      -- date arithmetic
    AGE(hire_date),                      -- e.g. "3 years 2 months"
    EXTRACT(YEAR FROM hire_date),        -- 2021
    DATE_TRUNC('month', hire_date),      -- first day of month
    TO_CHAR(hire_date, 'DD/MM/YYYY')     -- format as string
FROM employees;

-- Type casting
SELECT
    '42'::integer,           -- PostgreSQL cast syntax
    CAST('42' AS integer),   -- standard SQL cast
    42::text,
    '2026-06-10'::date
Commonly confused
WHERE filters rows before grouping; HAVING filters groups after grouping. You cannot use aggregate functions (COUNT, SUM, AVG) in a WHERE clause — they don't exist yet when WHERE runs. Use HAVING to filter on aggregates. A query with both: WHERE runs first on individual rows, GROUP BY groups them, then HAVING filters the groups.
NULL = NULL is NULL (unknown), not TRUE. In SQL, NULL represents an unknown value. Comparing NULL to anything — including another NULL — produces NULL, not TRUE or FALSE. This is why WHERE phone = NULL never matches anything. Always use IS NULL or IS NOT NULL.
SQL is case-insensitive for keywords but case-sensitive for data. SELECT and select are identical. But string comparisons respect case: WHERE name = 'priya' will not match "Priya". Use LOWER(name) = 'priya' or ILIKE (PostgreSQL) for case-insensitive search.
How this connects
Primary source

The query execution order

SQL queries are written in a specific order, but executed in a different order. The logical execution order is: (1) FROM — identify the base tables and joins; (2) WHERE — filter individual rows; (3) GROUP BY — group rows into sets; (4) HAVING — filter groups; (5) SELECT — compute output columns and expressions; (6) DISTINCT — remove duplicates; (7) ORDER BY — sort results; (8) LIMIT/OFFSET — restrict output count. This ordering explains why you cannot reference a SELECT alias in a WHERE clause (WHERE runs before SELECT computes aliases) but can reference it in ORDER BY (ORDER BY runs after SELECT).

The relational model and Codd's rules

SQL is based on Edgar F. Codd's relational model (1970 paper: "A Relational Model of Data for Large Shared Data Banks"). The model defines: relations (tables) as sets of tuples (rows); attributes (columns) have domains (types); the relational algebra defines operations (select σ, project π, join ⋈, union ∪, difference −, product ×). SQL's SELECT-FROM-WHERE corresponds to the relational algebra expression π(σ(R)) — project (SELECT columns) of a select (WHERE conditions) of a relation (FROM table). Codd defined 12 rules for a "fully relational" DBMS. No commercial database satisfies all 12; PostgreSQL satisfies the most.

Sources

1
PostgreSQL 16 Documentation — SELECT. postgresql.org/docs/current/sql-select.html.
2
ISO/IEC 9075-2:2023 — SQL Foundation. iso.org/standard/76583.html.
3
Codd, E. F. (1970). A Relational Model of Data for Large Shared Data Banks. Communications of the ACM, 13(6).
4
PostgreSQL 16 Documentation — Functions and Operators. postgresql.org/docs/current/functions.html.
Source confidence: High Last verified: Primary source: ISO/IEC 9075 · postgresql.org/docs/

Sources

1
PostgreSQL 16 — SELECT. postgresql.org/docs/current/sql-select.html.
2
ISO/IEC 9075-2:2023 — SQL Foundation. iso.org/standard/76583.html.
3
Codd, E. F. (1970). A Relational Model of Data. Communications of the ACM, 13(6).
4
PostgreSQL 16 — Functions and Operators. postgresql.org/docs/current/functions.html.