Emergency Reference
PostgreSQL Cheatsheet
The 50 functions you'll reach for most — compact syntax reminders designed for bookmarking, printing, and 2am emergencies.
🔤
String
20lower/upper→ textChange caselower(str) / upper(str)lower('Hello')→hellolength→ intCharacter countlength(str)length('café')→4trim→ textStrip leading/trailing charstrim([BOTH|LEADING|TRAILING] [chars] FROM str)trim(' hi ')→hisubstring→ textExtract by position or regexsubstring(str FROM start [FOR len])substring('hello' FROM 2 FOR 3)→ellreplace→ textLiteral string replacement (all occurrences)replace(str, from, to)replace('aXbX','X','!')→a!b!regexp_replace→ textRegex replacement; 'g' flag for all matchesregexp_replace(str, pat, repl [, flags])regexp_replace('a1b2','[0-9]','N','g')→aNbNsplit_part→ textReturn Nth field after splitting; safe out-of-boundssplit_part(str, delimiter, n)split_part('a,b,c',',',2)→bconcat_ws→ textJoin with separator, skipping NULLsconcat_ws(sep, val1, val2, ...)concat_ws(' ','John',NULL,'Doe')→John Doeformat→ text%s value, %I identifier, %L literal (injection-safe)format(fmt, arg1, ...)format('%I = %L','col','val')→col = 'val'lpad / rpad→ textPad to fixed widthlpad(str, len [, fill])lpad('42',6,'0')→000042strpos→ intPosition of substring; 0 if not foundstrpos(str, substr)strpos('hello','ll')→3left / right→ textFirst/last N chars; negative skips from other endleft(str, n) / right(str, n)right('abcdef',-2)→cdefinitcap→ textTitle-case each wordinitcap(str)initcap('hello world')→Hello Worldtranslate→ textCharacter-by-character substitution (single pass)translate(str, from, to)translate('hello','aeiou','*****')→h*ll*md5→ textMD5 hex digest (not for passwords)md5(str)md5('hello')→5d41402a...encode / decode→ text/byteaBase64 or hex encoding of binary dataencode(data, 'base64') / decode(str, 'base64')encode('Hi'::bytea,'base64')→SGk=regexp_match→ text[]Return capture groups of first regex matchregexp_match(str, pattern [, flags])(regexp_match('v14.2','v(\d+)'))[1]→14string_to_array→ text[]Split string into arraystring_to_array(str, delimiter)string_to_array('a,b,c',',')→{a,b,c}starts_with→ boolTest string prefixstarts_with(str, prefix)starts_with('hello','he')→truereverse→ textReverse a stringreverse(str)reverse('hello')→olleh📅
Date & Time
10now()→ timestamptzCurrent transaction start time (stable within transaction)now()SELECT now();→2024-03-15 14:30:00+00current_date→ dateCurrent date in session timezonecurrent_dateSELECT current_date;→2024-03-15date_trunc→ timestampTruncate to time unit precisiondate_trunc(unit, timestamp)date_trunc('month', now())→2024-03-01 00:00:00+00date_part / extract→ float8/numericExtract a field from a timestampextract(field FROM timestamp)extract(year FROM now())→2024age()→ intervalDifference between two timestampsage(timestamp, timestamp)age('2024-01-01','2023-01-01')→1 yearinterval arithmetic→ timestampAdd/subtract intervalstimestamp ± intervalnow() + interval '7 days'→now + 7 daysto_timestamp→ timestamptzConvert epoch seconds to timestampto_timestamp(double precision)to_timestamp(1700000000)→2023-11-14 22:13:20+00to_char (date)→ textFormat date/time as stringto_char(timestamp, format)to_char(now(),'YYYY-MM-DD')→2024-03-15timezone()→ timestampConvert timestamp to specified timezonetimezone(zone, timestamp)timezone('America/New_York', now())→Local NYC timemake_date→ dateBuild a date from year, month, daymake_date(year, month, day)make_date(2024,12,31)→2024-12-31🔢
Math
8round→ numericRound to n decimal placesround(v numeric, n int)round(3.14159, 2)→3.14floor / ceil→ numericRound down / up to nearest integerfloor(v) / ceil(v)floor(4.9)→4abs→ sameAbsolute valueabs(v)abs(-42)→42mod→ sameRemainder of divisionmod(a, b) or a % bmod(10, 3)→1power / sqrt→ float8Exponentiation / square rootpower(base, exp) / sqrt(v)power(2,10)→1024random()→ float8Random value in [0.0, 1.0)random()floor(random()*100)::int→Random 0–99trunc→ numericTruncate (toward zero), no roundingtrunc(v [, n])trunc(3.99)→3greatest / least→ sameMaximum / minimum of a listgreatest(a, b, ...) / least(a, b, ...)greatest(1,5,3)→5📦
JSON & JSONB
8-> / ->>→ json/textExtract JSON field (-> keeps JSON, ->> returns text)col->'key' or col->index'{"a":1}'::jsonb -> 'a'→1#> / #>>→ json/textExtract at path arraycol #> '{key,subkey}'data #>> '{user,name}'→Johnjsonb_set→ jsonbReplace or insert a value at pathjsonb_set(doc, path, new_val [, create])jsonb_set(doc, '{a}', '99')→doc with a=99jsonb_build_object→ jsonbBuild JSONB object from key-value pairsjsonb_build_object(k1, v1, k2, v2, ...)jsonb_build_object('id',1,'name','x')→{"id":1,"name":"x"}jsonb_agg→ jsonbAggregate rows into a JSON arrayjsonb_agg(expression)SELECT jsonb_agg(name) FROM users→["Alice","Bob"]jsonb_each→ setof (key,value)Expand JSONB object into key-value rowsjsonb_each(jsonb)SELECT * FROM jsonb_each('{"a":1}'::jsonb)→a | 1jsonb_array_elements→ setof jsonbExpand JSON array into rowsjsonb_array_elements(jsonb)SELECT * FROM jsonb_array_elements('[1,2,3]'::jsonb)→1,2,3 rowsrow_to_json→ jsonConvert a row to JSONrow_to_json(record)SELECT row_to_json(u) FROM users u LIMIT 1→{"id":1,"name":"..."}∑
Aggregate
6count→ bigintCount rows; count(*) includes NULLscount(*) / count(col)SELECT count(*) FROM users→1000sum / avg→ numericSum or average of non-NULL valuessum(col) / avg(col)avg(price)→24.99min / max→ sameMinimum / maximum valuemin(col) / max(col)max(created_at)→Most recent timestampstring_agg→ textConcatenate strings with separatorstring_agg(col, delimiter ORDER BY ...)string_agg(name,', ')→Alice, Bob, Carolarray_agg→ arrayCollect values into an arrayarray_agg(col ORDER BY ...)array_agg(id ORDER BY id)→{1,2,3}bool_and / bool_or→ booleanAll true / any true across rowsbool_and(condition)bool_and(active)→false if any inactive🪟
Window
6row_number()→ bigintUnique sequential row number within partitionrow_number() OVER (PARTITION BY ... ORDER BY ...)row_number() OVER (ORDER BY salary DESC)→1, 2, 3...rank() / dense_rank()→ bigintRank with/without gaps on tiesrank() OVER (...)rank() OVER (ORDER BY score DESC)→1,2,2,4 vs 1,2,2,3lag / lead→ sameValue from previous/next row in partitionlag(col, offset, default) OVER (...)lag(price,1,0) OVER (ORDER BY date)→Previous row's pricefirst_value / last_value→ sameFirst/last value in the window framefirst_value(col) OVER (...)first_value(price) OVER (PARTITION BY category ORDER BY date)→Oldest price in categoryntile(n)→ intDivide rows into n equal bucketsntile(n) OVER (ORDER BY ...)ntile(4) OVER (ORDER BY score)→1–4 quartile assignmentsum() OVER→ numericRunning total within windowsum(col) OVER (ORDER BY ... ROWS UNBOUNDED PRECEDING)sum(amount) OVER (ORDER BY date)→Cumulative sum🔀
Conditional
4COALESCE→ sameFirst non-NULL value in listCOALESCE(v1, v2, ...)COALESCE(nickname, first_name, 'Anonymous')→First non-null nameNULLIF→ sameNULL if two values are equalNULLIF(a, b)NULLIF(count, 0)→NULL instead of zeroCASE WHEN→ anyConditional expressionCASE WHEN cond THEN val ... ELSE val ENDCASE WHEN score>90 THEN 'A' ELSE 'B' END→Grade letterGREATEST / LEAST→ sameMax/min of arbitrary value list (NULL-skipping)GREATEST(a, b, ...) / LEAST(a, b, ...)GREATEST(0, col - 10)→0 if col < 10pgref.dev — PostgreSQL 16 — for complete docs with examples and pro tips, browse by category