On this page
Syntax (parse order in crates/sql/src/parser/select.rs)#
flowchart LR
T["TARGETS"] --> F["FROM + JOIN"] --> W["WHERE"] --> G["GROUP BY"] --> H["HAVING"] --> O["ORDER BY"] --> L["LIMIT / OFFSET"] --> S["set ops"]Diagram source · mermaidcopy included
flowchart LR
T["TARGETS"] --> F["FROM + JOIN"] --> W["WHERE"] --> G["GROUP BY"] --> H["HAVING"] --> O["ORDER BY"] --> L["LIMIT / OFFSET"] --> S["set ops"][WITH [RECURSIVE] cte,…]
SELECT [DISTINCT [ON (expr,… )]] target,…
[FROM relation,… | JOIN …]
[WHERE expr]
[GROUP BY expr,… | GROUPING SETS (…) | ROLLUP (…) | CUBE (…)]
[HAVING expr]
[ORDER BY expr [ASC|DESC] [NULLS FIRST|LAST],…]
[LIMIT n] [OFFSET n]
[FOR UPDATE]
[{UNION|INTERSECT|EXCEPT} [ALL] select]Targets#
SELECT *; SELECT users.*; SELECT u.* FROM users u;
SELECT id, name AS n, total * 1.1 AS with_tax FROM orders;
SELECT count(*) FILTER (WHERE total > 100) FROM orders;
SELECT sum(total) OVER (PARTITION BY user_id ORDER BY placed_at) FROM orders;
SELECT 1 AS schema; -- any keyword allowed as explicit AS aliasFROM#
FROM users, orders -- comma = CROSS
FROM users u JOIN orders o ON o.user_id = u.id
FROM users LEFT JOIN orders USING (id)
FROM (SELECT * FROM users) AS u(id, name)
FROM generate_series(1, 3) AS g(n) WITH ORDINALITY
FROM JSON_TABLE('…' , '$[*]' COLUMNS (a TEXT PATH '$.a')) AS jtUSING(a,b) rewrites to L.a=R.a AND …. Parenthesised joins need an alias (default __anon). LATERAL explicit or implicit when RHS references outer columns.
Filtering / grouping / ordering / pagination#
SELECT user_id, count(*), sum(total)
FROM orders WHERE total > 0
GROUP BY user_id HAVING count(*) > 1
ORDER BY sum(total) DESC NULLS LAST
LIMIT 20 OFFSET 40;
-- grouping sets / rollup / cube normalize to sets:
SELECT a, b, count(*) FROM t GROUP BY GROUPING SETS ((a,b),(a),());
SELECT a, b, count(*) FROM t GROUP BY ROLLUP (a, b);LIMIT/OFFSET accept only Int2/4/8 literals or casts. FOR UPDATE parses, ignored (single-writer serialization).
Set operations#
SELECT id FROM a UNION SELECT id FROM b;
SELECT id FROM a INTERSECT ALL SELECT id FROM b;
SELECT id FROM a EXCEPT SELECT id FROM b;Equal arity required; single-level left-assoc.
Behavior#
- Empty input → zero rows.
SELECTwithoutFROMevaluates expressions. - Ambiguous bare column → error.
SELECT *expands in join order. needs_general_engine:string_agg/array_agg/json_*agg, non-ColumnRefGROUP BY, multi-sets, or GROUP BY+ORDER BY route to the general join engine.
Constraints#
ILIKEparses but case-folding is ignored in the single-table path (behaves asLIKE).- Deeply nested subqueries guarded by
MAX_SUBQUERY_DEPTH.
Related: Joins · Aggregates · Subqueries + CTEs · EXPLAIN
Was this page helpful? Thanks — noted locally, nothing is sent anywhere.