Databases Cheatsheet

Quick reference for SQL syntax, JOIN types, normalization rules, ACID, and indexing.

SQLACIDNormalizationIndexing
NotesCheatsheet

SQL Quick Reference

-- SELECT / WHERE / ORDER / LIMIT
SELECT id, name FROM users WHERE active = true ORDER BY name LIMIT 20;

-- Aggregation: COUNT, SUM, AVG, MIN, MAX
SELECT dept, COUNT(*) AS n, AVG(salary) AS avg
FROM employees
GROUP BY dept
HAVING AVG(salary) > 60000;   -- HAVING filters groups; WHERE filters rows

-- Subquery
SELECT name FROM users WHERE id IN (SELECT user_id FROM orders WHERE total > 1000);

-- INSERT / UPDATE / DELETE
INSERT INTO users (name, email) VALUES ('Alice', 'a@b.com');
UPDATE users SET active = false WHERE last_login < '2024-01-01';
DELETE FROM sessions WHERE expires_at < NOW();

JOIN Types

-- INNER JOIN — only rows matching in BOTH tables
SELECT u.name, o.total FROM users u INNER JOIN orders o ON o.user_id = u.id;

-- LEFT JOIN — all rows from LEFT, NULL if no match on right
SELECT u.name, o.id FROM users u LEFT JOIN orders o ON o.user_id = u.id;
-- use: "all users, including those with no orders"

-- FULL OUTER JOIN — all rows from both; NULL where no match
-- RIGHT JOIN — opposite of LEFT (prefer LEFT for readability)

-- SELF JOIN — table joins itself
SELECT e.name AS emp, m.name AS manager
FROM employees e LEFT JOIN employees m ON m.id = e.manager_id;
JOINReturns
INNEROnly matching rows from both tables
LEFTAll left rows + matching right (NULL if no match)
RIGHTAll right rows + matching left (NULL if no match)
FULL OUTERAll rows from both; NULL where no match

Window Functions

-- RANK / ROW_NUMBER / DENSE_RANK within partitions
SELECT name, salary, dept,
  RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rank
FROM employees;

-- Running total
SELECT date, amount,
  SUM(amount) OVER (ORDER BY date) AS running_total
FROM transactions;

-- LAG / LEAD — previous / next row value
SELECT date, revenue,
  LAG(revenue, 1) OVER (ORDER BY date) AS prev_day
FROM daily_sales;

-- RANK vs DENSE_RANK: RANK skips (1,2,2,4); DENSE_RANK doesn't (1,2,2,3)

ACID Properties

LetterPropertyGuarantee
AAtomicityAll operations succeed or all are rolled back
CConsistencyTransaction takes DB from one valid state to another
IIsolationConcurrent transactions don't see each other's partial work
DDurabilityCommitted data persists even after crash
BEGIN;
  UPDATE accounts SET balance = balance - 500 WHERE id = 1;
  UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;   -- both succeed together, or ROLLBACK reverts both

Isolation Levels

LevelDirty ReadNon-repeatablePhantom
Read UncommittedYesYesYes
Read CommittedNoYesYes
Repeatable ReadNoNoYes
SerializableNoNoNo

Normalization Forms

FormRule
1NFAtomic values, no repeating groups, unique rows
2NF1NF + no partial dependencies (every non-key column depends on the whole PK)
3NF2NF + no transitive dependencies (non-key column can't depend on another non-key column)
BCNF3NF + every determinant is a candidate key

Indexing Rules

CREATE INDEX idx_email ON users(email);
CREATE INDEX idx_user_date ON orders(user_id, created_at);  -- composite

-- Composite index: leftmost prefix rule
-- (a, b, c) helps: WHERE a=?  |  WHERE a=? AND b=?
-- (a, b, c) won't help: WHERE b=?  alone

-- Index on: WHERE columns, JOIN columns, ORDER BY columns
-- Don't index: low-cardinality columns (boolean), rarely-queried columns
-- Cost: faster reads, slower writes (index maintained on every insert/update)

-- B-tree (default): good for = and range queries
-- Hash index: O(1) equality only, useless for BETWEEN/ORDER BY
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 42;  -- check plan

NoSQL Types

TypeExamplesBest for
DocumentMongoDB, FirestoreFlexible schema, nested/hierarchical data
Key-ValueRedis, DynamoDBCaching, sessions, rate limiting, leaderboards
Column-FamilyCassandra, HBaseWrite-heavy, time-series, wide column tables
GraphNeo4j, NeptuneSocial graphs, recommendations, fraud detection

Key Rules

  • Use LEFT JOIN to find rows with no match (WHERE right_table.id IS NULL).
  • 3NF is sufficient for most OLTP systems; denormalize for read-heavy analytics.
  • Default isolation in PostgreSQL = Read Committed; in MySQL InnoDB = Repeatable Read.
  • Composite index: always filter by the leftmost column first, or the index won't be used.
  • NoSQL doesn't replace SQL — pick based on data model, access pattern, and consistency needs.