SQL Cheatsheet

The everyday SQL statements, grouped and searchable — copy any one.

A searchable SQL cheatsheet covering SELECT, WHERE filtering, sorting and grouping, aggregates, joins, writing data and schema changes. Copy any statement with one click. Runs entirely in your browser, nothing is uploaded. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is the difference between an inner join and a left join?

An inner join returns only rows that have a match in both tables. A left join returns every row from the left table and fills in nulls where the right table has no match.

A fast, searchable reference for the SQL you write most days. Statements are grouped so you can jump straight to the right pattern: querying with SELECT, filtering with WHERE, sorting and grouping, aggregates, joins, writing data (INSERT, UPDATE, DELETE), and schema changes. Each entry has a plain-English description and a one-click copy button.

How it works

Type a keyword or describe the task — join, group by, insert, index — and the list filters in real time to matching statements. Click Copy on any one to put it on your clipboard, then adapt the table and column names in your own database client. Nothing is executed here; it is a reference you paste from.

Quick-reference examples

Grouped counts with a filter

SELECT status, COUNT(*) AS total
FROM orders
GROUP BY status
HAVING COUNT(*) > 10
ORDER BY total DESC;

Left join — keep all rows from the left table

SELECT u.id, u.name, o.total
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL;  -- users who never placed an order

Upsert pattern (PostgreSQL)

INSERT INTO sessions (user_id, token, created_at)
VALUES ($1, $2, NOW())
ON CONFLICT (user_id)
DO UPDATE SET token = EXCLUDED.token, created_at = NOW();

Window function — running total

SELECT
  created_at::date AS day,
  SUM(amount) OVER (ORDER BY created_at::date) AS running_total
FROM payments;

Schema — add a column with a default

ALTER TABLE users
ADD COLUMN verified_at TIMESTAMP DEFAULT NULL;

Patterns that trip people up

WHERE vs HAVING: WHERE filters rows before grouping; HAVING filters groups after aggregation. You cannot use SUM(amount) inside a WHERE clause — move it to HAVING.

ORDER of SQL clauses: The database evaluates FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT, but you write them in the slightly different order SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT. The logical evaluation order matters when you try to reference a SELECT alias inside a WHERE — you cannot, because WHERE runs before SELECT.

NULL comparisons: WHERE column = NULL never matches. Use WHERE column IS NULL or IS NOT NULL. This catches many silent bugs in join-based queries.

Implicit vs explicit joins: FROM a, b WHERE a.id = b.a_id and FROM a JOIN b ON a.id = b.a_id produce the same result, but the explicit JOIN syntax makes the join condition visually separate from the filter conditions in WHERE and is strongly preferred for readability.

TopicExample statement
QueryingSELECT * FROM users;
Filtering... WHERE created_at >= '2026-01-01'
Joins... a JOIN b ON a.id = b.a_id
WritingUPDATE users SET active = false WHERE id = 7;

Everything runs in your browser; nothing you type or copy is uploaded.