SQL Tutorial: GROUP BY, JOINs, Window Functions & Indexes
WHERE drops rows before grouping. HAVING drops groups after. One chapter on the clause order, the aggregates WHERE cannot see, and the query that should have filtered earlier.
What you will learn
- WHERE filters rows; HAVING filters groups
- Rows, pages, and what an index actually stores
- SELECT plans: seq scan vs index vs covering
- Transactions, isolation, and lost updates
- Normalization vs the query you have to serve
- Migrations without locking the product
- When Postgres is enough and when it is not
How it works
Broken queries and lost updates first. Then the schema, index, and isolation level that make the same write safe.
Chapters
- Function, Case, If: SQL Explained
- NULL is unknown, so = cannot find it: SQL Explained
- GROUP BY packs matching rows into one bucket: SQL Explained
- A name and a SUM need a bucket: SQL Explained
- WHERE drops rows before the buckets form: SQL Explained
- HAVING throws away buckets: SQL Explained
- HAVING filters groups: SQL Explained
- WHERE, then buckets, then HAVING: SQL Explained
- Having - General errors related to having: SQL Explained
- GROUP BY will not guess a naked column: SQL Explained
- WHERE cannot see a bucket. LIMIT runs last.: SQL Explained
- COUNT(customer) skips the unknown buyer: SQL Explained
- A join follows a foreign key: SQL Explained
- An anti-join keeps the row with no match: SQL Explained
- A self-join reads the same table twice: SQL Explained
- A subquery keeps the rows and still returns the average
- Price < ANY means cheaper than at least one: SQL Explained
- WITH names a table that lives for one query: SQL Explained
- A derived table is a query in the FROM list: SQL Explained
- WITH RECURSIVE keeps joining the rows it just found
- OVER() does the math and keeps every row: SQL Explained
- RANK() without ORDER BY is 1 on every row: SQL Explained
- NTILE(4) splits an ordered list into four buckets
- LAG reads the previous row. LEAD reads the next.
- FIRST_VALUE reads the first row of the order: SQL Explained
- Twenty patterns, each with a sample and a result
- A database is a stack, not a single store: SQL Explained
- The disk moves a page, not a row: SQL Explained
- A commit is durable when the log is durable: SQL Explained
- A row store fetches a record. A column store fetches one…
- A B-tree puts many keys in one page: SQL Explained
- An index has a structure, a storage layout, and a rule
- Clustered and non-clustered: SQL Explained
- Rowstore, columnstore, unique, and filtered: SQL Explained
- The index is useful when the predicate matches its order
- A range is a slice of the leaf: SQL Explained
- ORDER BY and GROUP BY can use the leaf order: SQL Explained
- Indexing a real feed: status filter, sort, cardinality…
- Why MySQL picks a B-tree over a hash index: SQL Explained
- B-tree height is why 100 million rows still take three reads
- A covering index skips the table, until it does not
- When an index exists and is still ignored or slow
- Random or sequential primary keys: where does the next row…
- Special cases: unique keys with NULL, JSON, maps, and long…
- The buffer pool: which pages stay in memory: SQL Explained
- The redo log makes a commit durable without writing the…
- The undo log can roll a change back and show an old version
- MVCC: readers do not block writers because old versions…
- A checkpoint moves the recovery starting line forward
- The replication log: changes other servers can replay
- ACID is four promises, and each one has a mechanism
- Atomic and consistent in practice: autocommit, errors…
- One object or many: where a transaction's promises start…
- Dirty, non-repeatable and phantom reads, replayed step by…
- Four isolation levels decide which anomalies you accept
- When the snapshot is taken, and why a write sees newer data
- Lost updates, write skew and phantoms: the bugs snapshots…
- Serializability: three ways to make concurrency look like…
- Concurrency control: lock, validate, order, or keep versions
- Locks: shared, exclusive, intention, row, range and table
- Distributed transactions: two-phase commit and what…
- Transaction mistakes that hide in plain sight, and the big…
- A database session from connect to disconnect: SQL Explained
- What really happens when you run an INSERT: SQL Explained
- What happens inside an UPDATE: SQL Explained
- Hotspot updates: many sessions, one row: SQL Explained
- DELETE is slow, DROP is not: how data really leaves
- How a database builds a query plan: SQL Explained
- The join method is how matching rows are found
- How joins run, and why they beat correlated subqueries
- LIMIT can stop. OFFSET still walks the skipped rows.
- A cursor seeks. OFFSET still counts the skipped rows.
- Pitfalls that make simple and similar SQL slow
- Ten questions before you trust a fast query: SQL Explained
- Why the first query is slow: cold reads: SQL Explained
- Temporary tables and sort files: when a query spills to disk
- Rate limiting a database: protect it before it falls over
- What makes a database stall for a moment: SQL Explained
- AI-assisted SQL analysis: from EXPLAIN to root cause
- InnoDB storage: clustered pages, change buffer, adaptive…
- InnoDB redo, the binlog and the two-phase commit between…
- InnoDB read views, undo purge and the history list
- InnoDB gap and next-key locks: why a range is locked when…
- A primary key is known before execution starts
- Reading MySQL EXPLAIN: const, ref, range, index and ALL
- MySQL settings that change query speed: SQL Explained
- MySQL diagnosis: slow log, optimizer trace, performance…
- PostgreSQL MVCC: tuple versions, VACUUM, HOT and wraparound
- PostgreSQL WAL, full-page writes and checkpoints
- PostgreSQL locks and isolation: snapshots, SSI and no gap…
- PostgreSQL index types: B-tree, GIN, GiST, BRIN, partial…
- Reading PostgreSQL EXPLAIN (ANALYZE, BUFFERS): SQL Explained
- PostgreSQL settings and diagnosis: shared_buffers…
- The engine you will build, one layer per chapter
- Find row 2 without reading every byte: SQL Explained
- TLV: every value says its own type and length: SQL Explained
- Insert, select, delete and update on a plain file
- A write-ahead log lets a crashed insert be replayed
- Cut the table file into pages the engine can find
- A B-tree index file turns a key into a file offset
- A small LRU cache saves most disk reads: SQL Explained
- A full-text index maps each word to the rows that hold it
- From SQL text to rows: parse, plan and iterators
- A database design interview in seven steps: SQL Explained
- Design the database for a Q&A site like Quora: SQL Explained
- Design the database for a short-video app like TikTok
- Design the database for a booking site like Airbnb
- Design the database for an ephemeral messaging app like…
- Who gets the last phone in a flash sale: SQL Explained
- Which database for a food delivery app: SQL Explained
- The cache expired and the database fell over: SQL Explained
- A live final: scale before the toss: SQL Explained
- An app like ChatGPT: the answer is written live
- A product Q&A box on sale day: SQL Explained
- Tatkal at 10:00: one seat, sold in stretches: SQL Explained
- A group chat: one register, many sockets: SQL Explained
- The ticket interview: you have AI, so they test judgement
- Interview: the same job runs twice: SQL Explained
- Interview: checkout fails with “Deadlock found”
- Interview: one keyword made the page 40× slower
- Interview: rate limit is 2/min, 30 requests get through
- Interview: “just add an index” slowed ingestion
- Interview: “I changed my name, refresh shows the old one”
- Interview: importing 10M rows takes six hours: SQL Explained
- Interview: everything got slow and the disk keeps growing
- Interview: wallet balance is wrong under load: SQL Explained
- Interview: API p99 jumps 10× every night at 2 am
- Interview: profile lookups got 40× slower, writes are fine
- Interview: inserts stall, and only one page is hot
- Interview: the write succeeded, the next read shows an…
- Interview: inventory stayed locked after the coordinator…
- Interview: for four minutes, both regions took orders
- Interview: shoes show a 0% discount, then the report crashes
- Interview: March gained $50 after the deploy, and the…
- Interview: the new branch’s dashboard takes 38 seconds
- Interview: the index is right there, make Postgres use it
- Interview: warehouse and checkout overwrite the same order
- Interview: the bestsellers report now takes nine minutes
- Interview: an analyst query locked checkout: SQL Explained
- Interview: the member is active and the email went out twice
- Interview: one shard is at 96% CPU and the other is idle
- Interview: the menu is slow, and the proposal is event…
- Interview: four dashboards disagree about whether the…
- Interview: checkout got slow the hour the warehouse job…
- Interview: the query is fast in staging and slow in…
- Interview: login looks up an email and reads the whole…
- Interview: the proposal splits one database into three…
- Interview: the order page joins four tables on every view
- Interview: every page view is a read-write query on the…
- Interview: Sarah and John both debit version 1
- Interview: the CTO read a blog post and wants to move…
- Interview: one table takes 50,000 writes a second, another…
- Interview: EU users wait on the ocean for every write, can…
- Interview: users search cars by color, but the table is…
- Interview: we added a fourth node and most of the data moved
- Interview: two people book the same room at noon, both get…
- Interview: everything is on the strongest consistency and…
- Interview: the order is saved, the message to search and…
- Interview: rename a column on a 600 GB table while 30…
- Interview: orders go to 16 shards in 2 regions, what…
- Interview: one celebrity posts, and every timeline in the…
- Interview: 5,000 customers share one database, and one of…
More courses
- Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
- Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
- React from open source with patterns — Patterns extracted from Material UI, Radix, React Aria, React Hook Form, Redux Toolkit, TanStack, and Next.js — not slides about hooks.
- System Design — Eight interview case studies, from a flash sale and Tatkal to a live final and a chat model, plus JWT in separate chapters.
- Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
- Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
- Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
- CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
- Accessibility — HTML labs first, then a full pass of WAI-ARIA 1.3: naming, every state, widget and structure roles, live regions, ariaNotify, and relationships.
- Docker — What an image is, why layers cache, and how containers find each other on a network.
- Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.