SQL reference
Queries, joins, aggregates, window functions and schema rules you reach for daily.
SQL describes the result you want, not the loop to get there. Write the relationship first, then filter, group and order. Check cardinality before trusting a result. Examples run in the SQL lab unless a note says PostgreSQL only.
Work through the guided lesson, then test yourself with a challenge.
Open courseAggregate functions
array_agg()
array_agg(expression)Collects group values into an array. PostgreSQL only.
Open entrybool_and() / bool_or()
bool_and(condition)True when every or any row matches. PostgreSQL; SQLite uses min()/max() on 0 and 1.
Open entrycount distinct
count(distinct expression)Counts unique non-null values.
Open entryevery()
every(condition)PostgreSQL alias for bool_and().
Open entrygroup_concat()
group_concat(expression, separator)Joins values from a group into one string. SQLite name for string_agg.
Open entryjson_group_array()
json_group_array(expression)Collects group values into a JSON array. SQLite and PostgreSQL.
Open entryjson_group_object()
json_group_object(key, value)Collects key-value pairs into a JSON object. SQLite only.
Open entrymode()
mode() within group (order by x)The most frequent value in a group. PostgreSQL.
Open entrypercentile_cont()
percentile_cont(0.5) within group (order by x)Continuous percentile, such as the median. PostgreSQL.
Open entrystddev()
stddev(expression)Sample standard deviation. PostgreSQL; most engines use a different name.
Open entrystring_agg()
string_agg(expression, delimiter)Concatenates group values with a delimiter. PostgreSQL and SQL Server.
Open entrysum(case …)
sum(case when … then 1 else 0 end)Counts rows that match a condition using only standard aggregate syntax.
Open entrytotal()
total(expression)Like sum() but returns 0.0 instead of NULL when there are no rows. SQLite only.
Open entryvariance()
variance(expression)Sample variance. PostgreSQL; most engines use a different name.
Open entryAggregation and grouping
count()
count(*) / count(column)count(*) counts rows; count(column) ignores NULLs.
Open entryfilter clause
count(*) filter (where …)Applies a condition to a single aggregate without splitting the query.
Open entrygroup by
group by columnCollapses rows into groups so aggregates run per group.
Open entrygroup by expression
group by date_trunc('month', created_at)Groups by a computed value. PostgreSQL needs the same expression in SELECT.
Open entryhaving
having aggregate_conditionFilters groups after aggregation, unlike WHERE which filters rows first.
Open entrymin() / max()
min(column)Returns the smallest or largest non-null value.
Open entryrollup
group by rollup (a, b)Adds subtotal rows for the grouping hierarchy. PostgreSQL only.
Open entrystring_agg / group_concat
string_agg(column, ', ')Joins group values into one string. SQLite calls it group_concat.
Open entrysum() / avg()
sum(column)Adds or averages non-null numeric values.
Open entryArray and set-returning functions
array_append()
array_append(array, value)Returns a new array with a value appended. PostgreSQL.
Open entryarray_length()
array_length(array, dimension)The length of an array dimension. PostgreSQL.
Open entryarray_position()
array_position(array, value)The one-based position of a value in an array. PostgreSQL.
Open entryarray_to_string()
array_to_string(array, delimiter)Joins an array into a string. PostgreSQL.
Open entrygenerate_series()
generate_series(start, stop, step)Generates a series of values. PostgreSQL; use a recursive CTE in SQLite.
Open entrystring_to_array()
string_to_array(text, delimiter)Splits a string into an array. PostgreSQL.
Open entryunnest()
unnest(array)Expands an array into rows. PostgreSQL; use json_each in SQLite.
Open entryVALUES as a table
values (1), (2)Builds an inline table without creating one. Works in PostgreSQL and SQLite.
Open entryDate and time functions
age()
age(later, earlier)A human-readable interval between timestamps. PostgreSQL.
Open entrycurrent_date
current_dateThe current date in UTC.
Open entrycurrent_time
current_timeThe current time in UTC.
Open entrycurrent_timestamp
current_timestampThe current date and time in UTC.
Open entrydate modifiers
date(now, 'start of month')SQLite modifiers such as start of month, weekday 1 and +3 hours.
Open entrydate()
date(timestring, modifier, …)Returns a date, optionally adjusted by modifiers such as +7 days.
Open entrydatetime()
datetime(timestring, modifier)Returns a full timestamp, optionally adjusted.
Open entryinterval arithmetic
date + interval '7 days'Adds or subtracts an interval. PostgreSQL and MySQL.
Open entryjulianday()
julianday(timestring)The Julian day number. Subtract two values to get a difference in days.
Open entrymake_date()
make_date(year, month, day)Builds a date from parts. PostgreSQL.
Open entrynow()
now()The current transaction timestamp. PostgreSQL; SQLite uses current_timestamp.
Open entrystrftime()
strftime(format, timestring)Formats a date using codes such as %Y, %m, %d and %H.
Open entrytime()
time(timestring)Returns the time portion of a timestamp.
Open entryto_char()
to_char(timestamp, format)Formats a timestamp with a picture string. PostgreSQL.
Open entryto_date()
to_date(text, format)Parses a date from a picture string. PostgreSQL.
Open entryunixepoch()
unixepoch(timestring)Seconds since the Unix epoch.
Open entryFunctions and expressions
cast()
cast(value as type)Converts between types. Use it explicitly rather than relying on implicit casts.
Open entryconcat()
concat(a, b)Joins strings, treating NULL as an empty string. The || operator returns NULL if any side is NULL.
Open entrycte
with name as (select …)A named temporary result set that makes complex queries readable.
Open entrycurrent_date / now()
current_date / now()The current date or timestamp. now() includes time and time zone in PostgreSQL.
Open entrydate_trunc()
date_trunc('month', ts)Truncates a timestamp to a unit, ideal for grouping by period.
Open entryexists
where exists (select 1 …)Tests whether a subquery returns any row. Often clearer and faster than IN with nulls.
Open entryextract()
extract(year from date)Reads a field from a date or timestamp. SQLite uses strftime().
Open entryGreatest / least
greatest(a, b)Returns the largest or smallest of the arguments. PostgreSQL and SQLite differ in null handling.
Open entrylag() / lead()
lag(column) over (…)Reads the previous or next row in a window, useful for deltas.
Open entrylength()
length(text)Character count of a string.
Open entrylower() / upper()
lower(text)Changes case for comparisons and display.
Open entrypartition by
over (partition by course order by …)Restarts a window calculation for each group.
Open entryposition()
position('x' in text)Finds a substring position, returning 0 when absent. SQLite uses instr().
Open entryrank() / dense_rank()
rank() over (…)Ranks rows, leaving gaps after ties; dense_rank leaves no gaps.
Open entryrecursive cte
with recursive …Walks a hierarchy such as a management chain or category tree.
Open entryreplace()
replace(text, from, to)Replaces every occurrence of a substring.
Open entryround()
round(value, places)Rounds a numeric value.
Open entryrow_number()
row_number() over (…)Assigns a sequential number to rows within a window.
Open entrysubquery
where id in (select …)A query nested inside another. Prefer JOINs when the relationship is simple.
Open entrysubstring()
substr(text, start, length)Extracts part of a string. SQLite uses substr(); PostgreSQL also accepts substring(text from start for length).
Open entrysum() over()
sum(x) over (order by …)A running total without collapsing rows, unlike GROUP BY.
Open entrytrim()
trim(text)Removes spaces from both ends. Use ltrim or rtrim for one side.
Open entryJoins and set operations
cross join
from a cross join bEvery row of a paired with every row of b. Use it deliberately; it multiplies row counts.
Open entryexcept
select … except select …Rows in the first result set that are not in the second.
Open entryfull outer join
from a full outer join b on …Keeps unmatched rows from both sides. SQLite does not support FULL OUTER JOIN.
Open entryinner join
from a join b on a.id = b.a_idKeeps only rows with a match on both sides.
Open entryintersect
select … intersect select …Rows present in both result sets.
Open entryleft join
from a left join b on …Keeps every left row and fills missing right columns with NULL.
Open entryright join
from a right join b on …Keeps every right row. Prefer swapping the tables and using LEFT JOIN for readability.
Open entryself join
from employee e join employee m on …Joins a table to itself, usually through two aliases.
Open entryunion
select … union select …Stacks result sets and removes duplicates. Column counts and compatible types must match.
Open entryunion all
select … union all select …Stacks result sets and keeps duplicates. Usually faster than UNION.
Open entryJSON functions
json ->> operator
json ->> '$.key'Reads a JSON value as text. PostgreSQL and SQLite.
Open entryjson_agg()
json_agg(expression)Aggregates rows into a JSON array. PostgreSQL; SQLite uses json_group_array().
Open entryjson_array()
json_array(value, …)Builds a JSON array from values.
Open entryjson_each
json_each(json)A table-valued function that expands a JSON array or object into rows.
Open entryjson_extract()
json_extract(json, path)Reads a value from a JSON document using a path.
Open entryjson_object()
json_object(key, value, …)Builds a JSON object from pairs.
Open entryjson_quote()
json_quote(value)Quotes a SQL value as JSON text.
Open entryjson_remove()
json_remove(json, path)Removes a value at a path.
Open entryjson_set()
json_set(json, path, value)Adds or replaces a value at a path.
Open entryjson_tree
json_tree(json)Walks a JSON document into rows with key, value, type and path.
Open entryjson_type()
json_type(json, path)The type of a JSON value: object, array, text, integer, real, true, false or null.
Open entryjson_valid()
json_valid(text)Returns 1 when the text is well-formed JSON.
Open entryjson()
json(text)Validates and stores a JSON text value.
Open entryjsonb functions
jsonb_set(jsonb, path, value)Binary JSON storage and update helpers. PostgreSQL only.
Open entryNumeric functions
abs()
abs(number)The absolute value.
Open entryasin() / acos() / atan()
asin(number)Inverse trigonometric functions returning radians.
Open entryatan2()
atan2(y, x)The angle of a vector, handling all quadrants.
Open entryceil() / floor()
ceil(number) / floor(number)Rounds up or down to an integer.
Open entrydegrees() / radians()
degrees(radians)Converts between radians and degrees.
Open entryexp()
exp(number)e raised to a power.
Open entryln()
ln(number)The natural logarithm. PostgreSQL and MySQL; SQLite builds without math functions may omit it.
Open entrylog()
log(base, number)A logarithm. PostgreSQL takes an explicit base; SQLite log(number) is base 10.
Open entrylog10()
log10(number)The base-10 logarithm.
Open entrymod()
mod(a, b)The remainder of a division. SQLite uses the % operator.
Open entrynumeric rounding
round(number, decimals)Rounds to a number of decimal places.
Open entrypi()
pi()The constant pi.
Open entrypower()
power(base, exponent)Raises a number to a power.
Open entryrandom()
random()A pseudo-random integer. Use it for sampling, not security.
Open entryrandomblob()
randomblob(bytes)Random bytes, useful for generating ids in SQLite.
Open entrysign()
sign(number)Returns -1, 0 or 1 depending on the sign.
Open entrysin() / cos() / tan()
sin(radians)Trigonometric functions that take radians.
Open entrysqrt()
sqrt(number)The square root.
Open entryto_number()
to_number(text, format)Parses a formatted number. PostgreSQL.
Open entrytrunc()
trunc(number, decimals)Truncates decimals without rounding. SQLite builds without math functions can use CAST.
Open entryReading data
and / or / not
where a and (b or c)Combines predicates. Use parentheses because AND binds tighter than OR.
Open entrybetween
where value between a and bAn inclusive range test.
Open entrycase expression
case when … then … else … endReturns different values based on conditions. It is an expression, so it can appear in SELECT, WHERE and ORDER BY.
Open entrycoalesce
coalesce(value, fallback)Returns the first non-null argument.
Open entrycolumn alias
select minutes * 60 as secondsRenames an output column. Quote aliases that contain spaces.
Open entrycomparison operators
= <> < > <= >=Compare values. Use IS NULL and IS NOT NULL for null checks, never = NULL.
Open entrydistinct
select distinct columnRemoves duplicate result rows. Use it deliberately because it costs sorting or hashing.
Open entrydistinct on
select distinct on (key) …PostgreSQL keeps the first row per key according to the ORDER BY. SQLite does not support it.
Open entryfetch first
fetch first 10 rows onlyStandard SQL pagination. PostgreSQL also supports LIMIT and OFFSET; SQLite only supports LIMIT.
Open entryin list
where status in (…)Matches any value in a list. Faster to read than chained ORs.
Open entryis null
where column is nullTests for the absence of a value. NULL never equals anything, including itself.
Open entrylike / ilike
where title like '%sql%'Pattern matching with % and _. LIKE is case-sensitive in PostgreSQL; ILIKE is not.
Open entrylimit
limit 10 offset 20Returns a page of rows. Offset pagination gets slower and can skip rows under concurrent writes.
Open entrynullif
nullif(a, b)Returns null when the two values are equal. Useful for avoiding division by zero.
Open entryorder by
order by column descSorts the result. Add a unique tie-breaker for stable pagination.
Open entryselect
select columns from table;Chooses the columns returned by a query. Prefer explicit columns over select * in application code.
Open entryselect *
select * from table;Returns every column. Convenient in exploration, risky in production because schema changes leak into results.
Open entrywhere
where conditionFilters rows before grouping. It cannot reference aggregate results; use HAVING for that.
Open entryRegular expressions and text search
~ operator
text ~ patternTests a POSIX regular expression. PostgreSQL.
Open entryregexp_like()
regexp_like(text, pattern)Tests a regular expression. MySQL and Oracle; PostgreSQL uses ~.
Open entryregexp_match()
regexp_match(text, pattern)Returns the first match of a regular expression. PostgreSQL.
Open entryregexp_matches()
regexp_matches(text, pattern, flags)Returns all matches as rows. PostgreSQL.
Open entryregexp_replace()
regexp_replace(text, pattern, replacement, flags)Replaces matches of a regular expression. PostgreSQL.
Open entrysimilar to
text similar to patternSQL standard pattern matching with more operators than LIKE. PostgreSQL; SQLite uses GLOB.
Open entryto_tsquery()
to_tsquery(config, query)Parses a full-text query. PostgreSQL.
Open entryto_tsvector()
to_tsvector(config, text)Builds a searchable text vector. PostgreSQL full-text search.
Open entryts_rank()
ts_rank(vector, query)Ranks documents against a full-text query. PostgreSQL.
Open entrywebsearch_to_tsquery()
websearch_to_tsquery(config, query)Parses a user-friendly search query. PostgreSQL.
Open entrySchema and constraints
alter table
alter table name add column …Changes an existing table. Some databases require a table rewrite for certain changes.
Open entrycheck
check (minutes > 0)Rejects rows that violate a domain rule.
Open entrycreate table
create table name (…);Defines a table and its columns, types and constraints.
Open entrycreate unique index
create unique index …Indexes a column and enforces uniqueness at the same time.
Open entrydefault
column integer default 0Supplies a value when the insert omits the column.
Open entrydrop table
drop table if exists nameRemoves a table and its data. IF EXISTS makes it safe to rerun a script.
Open entryforeign key
references other(id) on delete cascadeEnforces a relationship to another table and can cascade changes.
Open entryindex
create index name on table(col);Speeds up matching reads at the cost of writes and storage. Index the columns you filter and join on.
Open entrynot null
column text not nullRejects rows that leave the column empty. Add it to every column you always require.
Open entryprimary key
id bigint primary keyUniquely identifies each row and implies NOT NULL.
Open entryunique
column text uniqueRejects duplicate values across rows. Nulls are allowed multiple times in most databases.
Open entryString functions
ascii()
ascii(text)The code of the first character. SQLite uses unicode().
Open entrychar_length()
char_length(text)The number of characters. SQLite uses length().
Open entrychr()
chr(code)The character for a code point. SQLite uses char().
Open entryconcat_ws()
concat_ws(separator, …values)Joins values, skipping NULLs. SQLite 3.44+ and PostgreSQL.
Open entryformat()
format(template, …values)Builds a string with placeholders. SQLite 3.38+ and PostgreSQL.
Open entryinitcap()
initcap(text)Capitalises each word. PostgreSQL only.
Open entryinstr() with start
instr(text, substring)Finds a substring and returns a one-based position, or 0.
Open entryleft() / right()
left(text, n) / right(text, n)Takes characters from one end. PostgreSQL and SQL Server; SQLite uses substr().
Open entrylike with escape
like '%\%' escape '\'Escapes wildcard characters so they match literally.
Open entrylpad() / rpad()
lpad(text, length, fill)Pads a string to a fixed width. PostgreSQL; use printf() in SQLite.
Open entrymd5()
md5(text)The MD5 hash of a string. PostgreSQL and MySQL; never use it for passwords.
Open entryoctet_length()
octet_length(text)The number of bytes in a string’s encoding. PostgreSQL.
Open entryprintf()
printf(format, …values)Formats numbers and strings with printf-style placeholders. Very useful for padding in SQLite.
Open entryquote_literal()
quote_literal(text)Escapes a value for safe inclusion in SQL. PostgreSQL.
Open entryrepeat()
repeat(text, times)Repeats a string. PostgreSQL and MySQL; not built into SQLite.
Open entryreverse()
reverse(text)Reverses a string. PostgreSQL and MySQL; not built into SQLite.
Open entrysplit_part()
split_part(text, delimiter, n)Returns one part of a delimited string. PostgreSQL.
Open entrystrpos()
strpos(text, substring)The one-based position of a substring, or 0. SQLite uses instr().
Open entrysubstr() with negative start
substr(text, -n)A negative start counts from the end of the string.
Open entryto_hex()
to_hex(integer)Formats an integer as hexadecimal. PostgreSQL.
Open entrytrim() variants
trim(text, chars) / ltrim() / rtrim()Removes characters from both ends or one side.
Open entrySystem and metadata
changes()
changes()The number of rows changed by the most recent statement. SQLite.
Open entrycurrent_user
current_userThe current database user. PostgreSQL.
Open entryifnull()
ifnull(value, fallback)Returns the fallback when the first value is NULL. SQLite.
Open entryiif()
iif(condition, then, else)A compact conditional expression. SQLite.
Open entrylast_insert_rowid()
last_insert_rowid()The rowid generated by the most recent insert. SQLite.
Open entrynullifzero()
nullifzero(value)Returns NULL when the value is zero. Useful for safe division.
Open entrypragma function_list
pragma function_listLists every function the SQLite build provides.
Open entryquote()
quote(value)Returns a SQL literal for a value, with NULL rendered as NULL. SQLite.
Open entrysqlite_version()
sqlite_version()The SQLite library version. SQLite only.
Open entrytypeof()
typeof(expression)The storage class of a value: null, integer, real, text or blob. SQLite.
Open entryversion()
version()The server version string. PostgreSQL.
Open entryTransactions and integrity
explain
explain analyze select …Shows the query plan and real timings. Use it before adding an index.
Open entryisolation levels
set transaction isolation level …Controls how concurrent transactions see each other’s work. PostgreSQL defaults to READ COMMITTED.
Open entrylock rows
select … for updateLocks selected rows until the transaction ends, preventing lost updates. PostgreSQL and MySQL.
Open entryrollback
rollbackReverses the current transaction, discarding its changes.
Open entrysavepoint
savepoint name / rollback to nameMarks a point inside a transaction so part of it can be rolled back.
Open entrytransaction
begin; … commit;Groups statements so they succeed or fail together. A rollback undoes the whole group.
Open entryWindow functions
cume_dist()
cume_dist() over (…)The cumulative distribution of a row, from 0 to 1.
Open entryfirst_value()
first_value(column) over (…)The first value in the window frame.
Open entrylag() with default
lag(column, 1, 0) over (…)Uses a default when the previous row does not exist.
Open entrylast_value()
last_value(column) over (…)The last value in the current window frame. Widen the frame to see the group’s last row.
Open entrylead() with offset
lead(column, n) over (…)Looks ahead by n rows.
Open entrynamed window
window w as (order by …)Names a window definition and reuses it across several columns.
Open entrynth_value()
nth_value(column, n) over (…)The nth value in the window frame.
Open entryntile()
ntile(buckets) over (…)Splits rows into roughly equal buckets.
Open entrypercent_rank()
percent_rank() over (…)The relative rank of a row from 0 to 1.
Open entrywindow frame
rows between unbounded preceding and current rowDefines which rows an aggregate window sees. The default includes peers of the current row.
Open entryWriting data
delete
delete from table where …;Removes matching rows. Prefer soft deletes when audit history or recovery matters.
Open entryinsert
insert into table (cols) values (…);Adds rows. Always list columns explicitly so schema changes do not break the statement.
Open entryinsert from select
insert into t (cols) select …Copies rows from another query into a table.
Open entryinsert returning
insert … returning idReturns generated values such as ids from the inserted rows. PostgreSQL and SQLite support it.
Open entrymerge
merge into target using source on …Standard SQL for conditional insert, update and delete. PostgreSQL 15+ supports it.
Open entrytruncate
truncate table nameRemoves every row quickly and resets identity in PostgreSQL. It cannot be easily rolled back selectively.
Open entryupdate
update table set col = value where …;Changes matching rows. Always include a precise WHERE clause and check the affected count.
Open entryupdate from
update t set x = s.x from source s where …Updates rows using values from another table. PostgreSQL syntax; SQLite uses UPDATE … FROM as well.
Open entryupsert
insert … on conflict … do updateInserts or updates when a unique constraint is violated. PostgreSQL and SQLite support ON CONFLICT.
Open entryTurn the reference into recall.
Read the full lesson, then solve the challenge without looking. That is where the knowledge sticks.