Quick Reference · relational + spatial database · v2

postgreSQL + postGIS cheat sheet

SQL is written top-down (SELECT…FROM…WHERE) but the engine runs it in a fixed, different order — learn that order and half of SQL's "gotchas" stop being mysterious. PostGIS layers spatial types, ST_ functions, and GiST indexing on top, turning every table into a map.

psql client schema (DDL) data (DML) query / read admin & perf PostGIS destructive most common

Distilled & cross-checked across: postgresql.org · postgis.net · linuxize.com · quickref.me · tigerdata.com · geeksforgeeks.org · codecademy.com · gist.github.com/yokawasa · gist.github.com/Kartones · DataCamp · LearnSQL.com / Vertabelo

Logical query processing order

You write a query SELECT…FROM…WHERE…ORDER BY — but the planner executes it in this sequence. This is why a WHERE clause can't see a SELECT alias, and why ORDER BY can.

1 FROM / JOIN build the row set 2 WHERE filter rows (no aliases) 3 GROUP BY collapse into groups 4 HAVING filter the groups 5 SELECT DISTINCT compute & dedupe columns 6 ORDER BY sort — aliases work here 7 LIMIT / OFFSET trim the final rows EXECUTION RUNS LEFT → RIGHT you typed: SELECT…FROM…WHERE…GROUP BY…HAVING…ORDER BY…LIMIT (written order is almost the reverse of run order — window functions run between step 4 and step 5)

Core SQL

Connecting, schema, queries, writes, performance, and administration.

01Connect & psql Flagsthe command line
02psql Meta-Commandsthe backslash family
03Databases & Schemastop-level containers
04Create & Alter Tablesstructure
05Constraintsdata integrity rules
06Core Data Typeswhat to store columns as
07Query BasicsSELECT, sort, page
08FilteringWHERE clauses
09Joinscombine tables — see diagrams ↓
10Aggregation & Groupingsummarize rows
11Window Functionsper-row aggregates, keep every row
12Modifying Datawrite operations
13Transactionsall-or-nothing changes
14Indexes & Performancemake reads fast
15Roles & Privilegeswho can do what
16Text, Date & Castingcommon functions
17Backup, Restore & CSVmove data in & out
18Monitoring & Maintenancekeep it healthy

PostGIS — Spatial Extension

PostGIS turns PostgreSQL into a spatial database: new geometry/geography column types, ~300 ST_ functions, and GiST indexing over a coordinate plane or sphere.

19Setup & Geometry TypesPostGIS
20SRID, geometry vs geographythe #1 source of bugs
21Constructors & Accessorsbuild & inspect geometries
22Spatial Relationshipspredicates — see diagrams ↓
23Measurement & Processingcompute & transform
24Spatial Indexing & Loadingmake it fast, get data in
Reading the Placeholdersnotation used throughout

The four core joins

Same two tables, A and B — the shaded region is what each join keeps. Based on the standard SQL join-Venn convention.

INNER JOIN

Only rows where the join condition matches on both sides.

A B A ∩ B

LEFT JOIN

Every row from A, with matches from B where they exist (else NULL).

A B all of A

RIGHT JOIN

Every row from B, with matches from A where they exist (else NULL).

A B all of B

FULL OUTER JOIN

Every row from both sides; unmatched columns come back NULL.

A B A ∪ B
GROUP BY vs. window function

Both compute an aggregate per group — but GROUP BY collapses rows down to one per group, while a window function keeps every original row and attaches the aggregate alongside it.

GROUP BY col row, row, row row, row 1 summary row / group fn() OVER (PARTITION BY col) row + agg row + agg row + agg row + agg every row kept, all 4 see the same per-partition value
PostGIS spatial index: filter, then refine

Index-aware predicates (ST_Intersects, ST_Contains, ST_Covers, ST_DWithin…) run in two phases automatically — you just write the predicate.

1 · FILTER GiST R-Tree compares bounding boxes only fast · approximate · may over-include → candidate rows 2 · REFINE exact ST_ predicate runs on candidates only slower · exact · confirms real matches → final result ST_Disjoint & ST_Relate are negations — they skip the filter phase entirely full scan — avoid on big tables ⚠ not index-aware

Reading the four common predicates

A square (table A) and a circle (table B) — the shaded/highlighted part is what each predicate tests true for.

ST_Intersects

True if A and B share any point at all — the broadest, most common test.

A B shares any point

ST_Contains / ST_Within

True if one geometry's interior fully encloses the other.

A B A contains B

ST_Touches

True only if boundaries meet — interiors never overlap.

A B shared edge only

ST_DWithin

True if a target lies inside a buffer distance d — index-aware proximity search.

A in out within distance d

Worth memorizing

WHERE ≠ HAVINGWHERE filters rows before grouping; HAVING filters the groups
DELETE ≠ TRUNCATEDELETE is row-by-row, logged, supports WHERE; TRUNCATE is instant, no WHERE
= NULL is always falseNULL has no equality — use IS [NOT] NULL
SERIAL ≠ IDENTITYSERIAL is legacy sugar; GENERATED ALWAYS AS IDENTITY is the SQL standard
VACUUM ≠ ANALYZEVACUUM reclaims dead-row space; ANALYZE refreshes planner statistics
no USE statementPostgres has no USE db — switch with \c inside psql
UNIQUE index ≠ PRIMARY KEYboth enforce uniqueness, but UNIQUE permits one NULL
autocommit is oneach statement commits immediately unless wrapped in BEGIN…COMMIT
RANK ≠ DENSE_RANKRANK leaves gaps after ties (1,2,2,4); DENSE_RANK doesn't (1,2,2,3)
window fns run after HAVINGthey can't be used in WHERE/HAVING — wrap the query and filter in an outer SELECT
geometry ≠ geographygeometry is planar & degrees on 4326; geography is spherical & always metres
ST_MakePoint defaults to SRID 0always wrap it: ST_SetSRID(ST_MakePoint(lon,lat), 4326)
PostGIS order is (X, Y)that's (longitude, latitude) — the reverse of how people say "lat/lon"
ST_SetSRID ≠ ST_TransformSetSRID only labels the data; Transform actually reprojects the coordinates