DevToolsForYou

SQL Cheatsheet

A quick reference for SQL — SELECT queries, filtering, joins, aggregates, subqueries, DDL, and common functions.

Updated Apr 11, 2026

Sections

  1. Basic SELECT
  2. Filtering (WHERE)
  3. Joins
  4. Aggregates & Grouping
  5. Subqueries & CTEs
  6. DDL — Creating & Modifying Tables
  7. Common Data Types

Basic SELECT

ClauseExampleDescription
SELECTSELECT name, age FROM usersChoose columns to return
SELECT *SELECT * FROM usersReturn all columns
DISTINCTSELECT DISTINCT country FROM usersDeduplicate result rows
ASSELECT name AS full_name FROM usersAlias a column or table
LIMITSELECT * FROM users LIMIT 10Return at most N rows
OFFSETSELECT * FROM users LIMIT 10 OFFSET 20Skip N rows (pagination)
ORDER BYSELECT * FROM users ORDER BY age DESCSort results (ASC default)

Filtering (WHERE)

OperatorExample
=WHERE age = 30
<> / !=WHERE status <> 'inactive'
< > <= >=WHERE age >= 18 AND age <= 65
BETWEENWHERE age BETWEEN 18 AND 65
INWHERE country IN ('US', 'UK', 'CA')
NOT INWHERE role NOT IN ('admin', 'superuser')
LIKEWHERE name LIKE 'A%' -- starts with A
ILIKEWHERE name ILIKE '%smith%' -- case-insensitive (PostgreSQL)
IS NULLWHERE deleted_at IS NULL
IS NOT NULLWHERE email IS NOT NULL
AND / OR / NOTWHERE active = true AND (role = 'admin' OR role = 'mod')

Joins

Join TypeSyntaxReturns
INNER JOINFROM a INNER JOIN b ON a.id = b.a_idRows with matching keys in both tables
LEFT JOINFROM a LEFT JOIN b ON a.id = b.a_idAll rows from a; nulls for b where no match
RIGHT JOINFROM a RIGHT JOIN b ON a.id = b.a_idAll rows from b; nulls for a where no match
FULL OUTER JOINFROM a FULL OUTER JOIN b ON a.id = b.a_idAll rows from both, nulls where no match
CROSS JOINFROM a CROSS JOIN bCartesian product — every a paired with every b
SELF JOINFROM employees e1 JOIN employees e2 ON e1.manager_id = e2.idJoin a table with itself

Aggregates & Grouping

Clause / FunctionExampleDescription
COUNT(*)SELECT COUNT(*) FROM ordersCount all rows
COUNT(col)SELECT COUNT(email) FROM usersCount non-null values
SUMSELECT SUM(amount) FROM paymentsSum of values
AVGSELECT AVG(score) FROM resultsAverage of values
MIN / MAXSELECT MIN(price), MAX(price) FROM productsMinimum / maximum value
GROUP BYSELECT country, COUNT(*) FROM users GROUP BY countryGroup rows and aggregate
HAVINGGROUP BY country HAVING COUNT(*) > 100Filter groups (like WHERE but post-aggregate)

Subqueries & CTEs

PatternExample
Subquery in WHERESELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE active = true)
Subquery in FROMSELECT avg_order.* FROM (SELECT user_id, AVG(amount) avg FROM orders GROUP BY user_id) avg_order
CTE (WITH)WITH active_users AS (SELECT id FROM users WHERE active = true) SELECT * FROM orders WHERE user_id IN (SELECT id FROM active_users)
EXISTSSELECT * FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)

DDL — Creating & Modifying Tables

StatementExample
CREATE TABLECREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE, created_at TIMESTAMPTZ DEFAULT NOW())
ALTER TABLEALTER TABLE users ADD COLUMN phone TEXT
ALTER COLUMNALTER TABLE users ALTER COLUMN name TYPE VARCHAR(255)
DROP TABLEDROP TABLE IF EXISTS sessions
CREATE INDEXCREATE INDEX idx_users_email ON users(email)
DROP INDEXDROP INDEX IF EXISTS idx_users_email

Common Data Types

TypeDescription
INTEGER / INT4-byte integer
BIGINT8-byte integer — use for IDs on large tables
SERIAL / BIGSERIALAuto-incrementing integer (PostgreSQL)
TEXTVariable-length string (no length limit in PostgreSQL)
VARCHAR(n)Variable-length string with max length n
BOOLEANtrue / false
NUMERIC(p,s)Exact decimal — use for money
FLOAT / REALApproximate decimal — avoid for money
DATECalendar date (no time)
TIMESTAMPDate and time (no timezone)
TIMESTAMPTZDate and time with timezone (stores as UTC)
JSON / JSONBJSON document (JSONB is binary, indexable — prefer it)
UUID128-bit universally unique identifier