🧮 Learn SQL
You type every query yourself, against a real business database — from your first SELECT to window functions, CTEs and query tuning. Every lesson ships with runnable koans.
Short on time? The 25 episodes marked core are the shortest path to being productive at work. Start there and pick up the rest whenever a job asks for them.
Series 1 · SQL Fundamentals
SELECT, WHERE, GROUP BY and your first JOIN
- 01
Start Here: The SQL Thinking Loop — Your First Query, CloudBeaver & the Koans
The fastest way to learn SQL is to write it. You answer a real business question in your first few minutes, learn the loop you'll use every time, and meet the tools you'll practise with: Northwind on PostgreSQL, CloudBeaver, DuckDB and the koans.
corebeginner#sql#fundamentals#getting-started - 02
SELECT & Column Lists — Fetching a Table's Data
Open a database you have never seen and find out what is in it. Ask a table for everything, then ask it for exactly the columns you want, and read what the database says each column is made of.
corebeginner#sql#fundamentals#select - 03
Data Types — What a Column Can Hold, and Why Results Surprise You
Every column has a type, and whoever built the table chose it. Learn to ask any database what it is holding, meet the five families you will actually use, and see why a comparison can hand you an answer that looks right and is not.
corebeginner#sql#fundamentals#data-types - 04
WHERE, AND/OR/NOT, IN, BETWEEN — Keeping Only the Rows You Need
Ask a question and get back only the rows that answer it. One test with =, combined tests with AND and OR (and the parentheses trap between them), lists with IN, ranges with BETWEEN, and the date habit that never miscounts a month.
corebeginner#sql#fundamentals#where#filtering - 05
ORDER BY, LIMIT & FETCH FIRST — Sorting Rows and Keeping the Top Few
Every request that says top, latest, biggest or worst is a sort and a cut. Learn to put rows in the order you want, keep only the few you need, and see why the same query can hand two people different answers.
corebeginner#sql#fundamentals#order-by#limit - 06
Aliases, Expressions & DISTINCT — Make Messy Output Look Like a Report
A correct query is only half the job. Name your columns, build the ones the table hasn't got, round money back into money — and learn why a DISTINCT list stops being distinct the moment you add a column to it.
corebeginner#sql#fundamentals#alias#distinct#expressions - 07
Aggregate Functions: COUNT, SUM, AVG, MIN, MAX — Turning Many Rows Into One Number
How many, how much, the biggest, the smallest, the average. Learn the five functions that collapse a table into a single number — and the two invisible things that decide which rows that number is actually about.
corebeginner#sql#fundamentals#aggregate-functions#count - 08
GROUP BY — One Number per Customer, per Month, per Anything
An aggregate gives you one number for a whole table, and nobody ever asks for that. Learn to get one number per group — and why the columns you group by decide what one row of your report actually means.
corebeginner#sql#fundamentals#group-by#aggregates - 09
HAVING vs WHERE — Filtering Groups and Filtering Rows
You can build a total. Now keep only the groups you want. Learn what HAVING does, the order a database really runs your query in, and why putting a filter one clause too early gives you a wrong answer that proves itself right.
corebeginner#sql#fundamentals#having#group-by - 10
JOINs: INNER, LEFT, RIGHT, FULL — Combining Rows From Two Tables
The data you need is almost never in one table. Learn to match rows across two tables with JOIN and ON, keep the rows that match nothing, and see why moving one condition from ON into WHERE silently undoes a LEFT JOIN.
corebeginner#sql#fundamentals#joins#left-join - 11
NULL & Three-Valued Logic — How Missing Values Change Your Results
An empty cell is not a value, so comparing it to one answers neither yes nor no. Learn why = NULL matches nothing, why a filter and its opposite do not add up, and the two places a missing value quietly changes a number you were about to send someone.
corebeginner#sql#fundamentals#null#three-valued-logic#coalesce - 12
SELECT + JOIN + GROUP BY — Building Your First Real Report
Build a top 10 customers report with SELECT, JOIN, GROUP BY, SUM, ORDER BY and LIMIT, and learn the two checks that show whether its numbers are right before anybody acts on them.
corebeginner#sql#fundamentals#join#group-by#reporting#project
Series 2 · Intermediate SQL
CTEs, subqueries and window functions on real questions
- 01
Subqueries — Using One Query's Result Inside Another
Put a query in brackets inside another query: compare with the value it returns, test a list with IN, or query the table it builds, and check which average you are really comparing with.
coreintermediate#sql#intermediate#subqueries#in#having#grain - 02
CASE — SQL's If/Then for Labels & Buckets
coreintermediatecoming soon - 03
Dates & Times — Getting Ranges and Boundaries Right
coreintermediatecoming soon - 04
Multi-Table JOINs & Grain — When a Join Silently Drops or Multiplies Your Rows
coreintermediatecoming soon - 05
CTEs (WITH) — Breaking a Long Query Into Named Steps
coreintermediatecoming soon - 06
VIEWs, CREATE TABLE AS & Temp Tables — Save the Query, or Save Its Answer
intermediatecoming soon - 07
EXISTS & Correlated Subqueries — Questions About Each Row, and the NOT IN Trap
coreintermediatecoming soon - 08
Self-JOINs & Hierarchies — Relating Rows to Other Rows in the Same Table
intermediatecoming soon - 09
Window Functions I: OVER, PARTITION BY & ROW_NUMBER — The Latest Row per Customer
coreintermediatecoming soon - 10
String Functions, LIKE & Regex — Clean Up Messy Real-World Data
coreintermediatecoming soon - 11
Window Functions II: LAG/LEAD, Running Totals & Frames — Month-over-Month Growth in One Query
coreintermediatecoming soon - 12
UNION, INTERSECT, EXCEPT — Stacking and Reconciling Result Sets
coreintermediatecoming soon - 13
GROUPING SETS, ROLLUP & CUBE — Subtotals and Grand Totals in One Pass
intermediatecoming soon - 14
INSERT, UPDATE, DELETE & Transactions — Change the Data, Safely
coreintermediatecoming soon - 15
UPSERT & MERGE — Insert or Update in One Statement, and Loads You Can Run Twice
coreintermediatecoming soon - 16
Median and Percentiles — WITHIN GROUP, and Why AVG Is Not the Answer
intermediatecoming soon - 17
Subqueries + CTEs + Window Functions — Solving a Real Business Case, End to End
coreintermediate#projectcoming soon - 18
Subqueries (v2 pilot) — Using One Query's Result Inside Another
Put a query in brackets inside another query: compare with the value it returns, test a list with IN, or query the table it builds, and check which average you are really comparing with.
intermediate#sql#intermediate#subqueries#in#having#grain
Series 3 · Advanced SQL
the harder queries, and how to make a slow one fast
- 01
PIVOT & UNPIVOT — Turn Rows into a Cross-Tab Report, the Portable Way
advancedcoming soon - 02
JSON in SQL — Query Semi-Structured Data Without Leaving the Database
advancedcoming soon - 03
Recursive CTEs — Walk an Org Chart to the Top
advancedcoming soon - 04
Gaps & Islands — Find Streaks, Runs and Missing Periods
advancedcoming soon - 05
Cohorts & Repeat-Purchase Analysis — Measuring Who Comes Back, and When
advancedcoming soon - 06
Writing a Query That Can Be Fast — Filter Early, Don't Hide the Column
advancedcoming soon - 07
EXPLAIN / EXPLAIN ANALYZE — Reading the Plan to Find Out Why a Query Is Slow
advancedcoming soon - 08
Rewrites That Change the Plan — EXISTS, DISTINCT and Deep Pagination
advancedcoming soon - 09
Indexes — Making a Query Faster, and What an Index Costs
advancedcoming soon - 10
COUNT(DISTINCT) — the Aggregate That Will Not Decompose
advancedcoming soon - 11
Query Tuning — Making a Real Slow Query Fast
advanced#projectcoming soon
Series 4 · Cross-Vendor SQL
one query, five databases
- 01
ANSI SQL vs Dialects — Why SQL That Works Here Fails on Another Database
advancedcoming soon - 02
Portable Paging, Strings, Dates & UPSERT — One Query That Runs on Every Engine
advancedcoming soon - 03
Northwind on Postgres, Oracle, SQL Server, MySQL & Db2 — One Query, Five Databases
advanced#projectcoming soon
Where this leads
- AI for Data — starts from Series 2.
- Analytics Engineering with dbt — starts from Series 2.
- Apache Spark — starts from Series 1 and Series 2.
- BI & Data Visualization — starts from Series 2.
- Build Your Own: ERP & CRM — starts from Series 1.
- ClickHouse — starts from Series 1 and Series 2.
- Data Modeling — starts from Series 1 entire, plus INSERT … SELECT from Series 2.
- Data Ops — starts from Series 1.
- Data Warehousing — starts from Series 2.
- Database X vs Database Y — starts from Series 1 and Series 2.
- DuckDB — starts from Series 1 and Series 2.
- ETL & Data Pipelines — starts from Series 1.
- IBM Db2 — starts from Series 1 and Series 2.
- Java & Groovy for Data — starts from Series 1.
- MySQL & MariaDB — starts from Series 1 and Series 2.
- Neo4j — starts from Series 2, and Series 3.
- Next.js — starts from Series 1, and Series 2.
- Oracle Database — starts from Series 1 and Series 2.
- PostgreSQL — starts from Series 1 and Series 2.
- Python for Data — starts from Series 1.
- SQL Server — starts from Series 1 and Series 2.
- SQLite — starts from Series 1.
Not here, on purpose
- DDL, keys, constraints & normalization — covered in Learn Data Modeling — it's schema design, not writing queries
- Whether a column should be nullable at all — covered in Data Modeling, Series 1, which is the design decision. In this course, Series 1 · 45 is what NULL does to a query
- Deciding to store JSON in the first place — covered in Data Modeling, Series 2. In this course, Series 3 queries JSON once that decision has been made
- Choosing indexes while designing the schema — covered in Data Modeling, Series 2. In this course, Series 3 is EXPLAIN and the mechanics, on a query that already exists
- Isolation levels, locking & concurrency — covered in Data Ops, Series 2 — Running PostgreSQL in Production. In this course, Series 2 · 55 covers the COMMIT and ROLLBACK basics
- Stored procedures, functions and triggers — covered in each engine's own course, because the procedural languages share almost no syntax — PostgreSQL, SQL Server, Oracle Database, and MySQL & MariaDB. In this course, SQL is what you send, not what runs inside the server
- OLAP cubes and the warehouse use of ROLLUP / CUBE — covered in Data Warehousing: Series 1 uses them over a star schema and Series 2 builds OLAP cubes. In this course, Series 2 · 50 is the SQL itself (GROUPING SETS, ROLLUP, CUBE, GROUPING())
- Exporting query results to a file (COPY, \copy, client export) — covered in ETL & Data Pipelines, Series 1, where a file is a sink you write to and the permissions and row-count checks come with it. In this course a result set is something you read, not a file you produce