SQL Crash Course · Page 3

SQL: the data skill
every AI engineer needs.

Models are only as good as the data you feed them — and SQL is how you get that data. This page teaches the 90% of SQL you'll actually use, right here, with a cheat sheet and hand-picked practice resources at the end.

8 core topics, all on this page Cheat sheet included 8 verified practice links

Why Bother

Where SQL shows up in AI work

Feeding your models

Training sets, RAG corpora, and fine-tuning data all start as SQL queries against someone's database.

Analysing evals & logs

"Which model scored best last week?" is a GROUP BY, not a dashboard you wait three days for.

Vector databases speak SQL

pgvector turns Postgres into a vector store — your RAG retrieval can literally be a SELECT.

Interviews

Almost every AI/data role screens SQL. It's the easiest interview section to score full marks on.

The Mental Model

A query is a question about tables

A database is a set of tables (like spreadsheets): rows are records, columns are fields. All examples below use two tables you might have in a real AI project: evals(id, model, question, score, latency_ms, created_at) and models(name, provider, cost_per_1k).

The one rule that unlocks SQL: queries don't run top-to-bottom. The engine executes FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. That's why you can't use a SELECT alias inside WHERE — WHERE runs first.

The Crash Course

Eight topics = 90% of daily SQL

1 · Reading rows — SELECT, WHERE, ORDER BY, LIMIT

Pick columns, filter rows, sort, and cap the result.

-- The 10 worst-scoring answers from claude models this week
SELECT question, score, latency_ms
FROM evals
WHERE model LIKE 'claude%'
  AND created_at >= '2026-07-28'
ORDER BY score ASC
LIMIT 10;

Operators: = != < > BETWEEN IN (…) LIKE (with % wildcard) IS NULL. Combine with AND / OR / NOT.

2 · Summarising — COUNT, AVG, GROUP BY, HAVING

Collapse many rows into stats per group. This is the query you'll write most.

-- Average score and volume per model, best first — models with 50+ runs only
SELECT model,
       COUNT(*)            AS runs,
       ROUND(AVG(score), 2) AS avg_score
FROM evals
GROUP BY model
HAVING COUNT(*) >= 50
ORDER BY avg_score DESC;

WHERE filters rows before grouping; HAVING filters groups after. Aggregates: COUNT SUM AVG MIN MAX.

3 · Combining tables — JOIN

Match rows across tables on a shared key.

-- Add provider and cost info to every eval row
SELECT e.model, m.provider, e.score, m.cost_per_1k
FROM evals e
JOIN models m ON e.model = m.name;

-- LEFT JOIN: keep ALL evals, even if the model isn't in the models table
SELECT e.model, m.provider
FROM evals e
LEFT JOIN models m ON e.model = m.name
WHERE m.name IS NULL;   -- finds evals with no matching model — a classic data check

JOIN (inner) keeps only matches. LEFT JOIN keeps every left row, filling the right side with NULLs. Those two cover ~95% of real joins.

4 · Readable pipelines — CTEs (WITH)

Name intermediate results instead of nesting subqueries five levels deep.

-- Which models beat the overall average?
WITH per_model AS (
  SELECT model, AVG(score) AS avg_score
  FROM evals
  GROUP BY model
),
overall AS (
  SELECT AVG(score) AS avg_all FROM evals
)
SELECT p.model, p.avg_score
FROM per_model p, overall o
WHERE p.avg_score > o.avg_all;

CTEs run top to bottom and read like steps in a pipeline — reviewers (and future you) will thank you.

5 · Ranking & trends — window functions

Compute per-row stats without collapsing rows — rank, running totals, previous value.

-- Best answer per model (rank within each model's rows)
SELECT model, question, score,
       ROW_NUMBER() OVER (PARTITION BY model ORDER BY score DESC) AS rank
FROM evals;
-- wrap it in a CTE and keep WHERE rank = 1 → "top answer per model"

-- Did latency improve vs the previous run?
SELECT created_at, latency_ms,
       latency_ms - LAG(latency_ms) OVER (ORDER BY created_at) AS delta
FROM evals WHERE model = 'claude-sonnet-5';

Pattern: fn() OVER (PARTITION BY … ORDER BY …). Learn ROW_NUMBER, RANK, LAG/LEAD, and windowed SUM/AVG — interviewers love these.

6 · Writing data — INSERT, UPDATE, DELETE, CREATE

The other half of CRUD. Handle with care.

CREATE TABLE evals (
  id         SERIAL PRIMARY KEY,
  model      TEXT NOT NULL,
  question   TEXT,
  score      REAL,
  latency_ms INTEGER,
  created_at TIMESTAMP DEFAULT now()
);

INSERT INTO evals (model, question, score, latency_ms)
VALUES ('claude-sonnet-5', 'What is RAG?', 0.92, 840);

UPDATE evals SET score = 0.95 WHERE id = 42;
DELETE FROM evals WHERE created_at < '2025-01-01';

Never run UPDATE or DELETE without a WHERE clause. Habit: write the same condition as a SELECT first, check what comes back, then swap the verb.

7 · Making it fast — indexes & EXPLAIN

Enough performance knowledge to not be dangerous.

-- Speed up the columns you filter/join on constantly
CREATE INDEX idx_evals_model_time ON evals (model, created_at);

-- Ask the database how it will run your query
EXPLAIN ANALYZE
SELECT * FROM evals WHERE model = 'claude-sonnet-5';

Rules of thumb: index your WHERE/JOIN columns, avoid SELECT * in production code, and if a query is slow, read EXPLAIN before guessing.

8 · SQL × AI — vector search with pgvector

This is where SQL meets your roadmap's Phase 3: RAG retrieval as a query.

-- Postgres + the pgvector extension = a vector database
CREATE EXTENSION vector;

CREATE TABLE chunks (
  id        SERIAL PRIMARY KEY,
  doc       TEXT,
  content   TEXT,
  embedding vector(768)          -- one embedding per chunk
);

-- Top-5 most similar chunks to a query embedding (cosine distance: <=>)
SELECT content, 1 - (embedding <=> $query_embedding) AS similarity
FROM chunks
ORDER BY embedding <=> $query_embedding
LIMIT 5;

JSON is the other AI-adjacent power tool: Postgres JSONB columns store raw LLM outputs and let you query into them with ->>.

Quick Reference

The cheat sheet

Clause / keywordWhat it doesExample
SELECT … FROMChoose columns from a tableSELECT model, score FROM evals
WHEREFilter rows (before grouping)WHERE score > 0.8 AND model LIKE 'claude%'
ORDER BY … LIMITSort and cap resultsORDER BY score DESC LIMIT 10
GROUP BYOne row per group + aggregatesGROUP BY model
HAVINGFilter groups (after grouping)HAVING COUNT(*) >= 50
JOIN … ONMatch rows across tablesJOIN models m ON e.model = m.name
LEFT JOINKeep all left rows, NULL-fill rightLEFT JOIN models m ON …
WITH (CTE)Name a sub-result, build pipelinesWITH top AS (SELECT …) SELECT * FROM top
OVER (PARTITION BY)Window: per-row stats without collapsingROW_NUMBER() OVER (PARTITION BY model ORDER BY score DESC)
CASE WHENIf/else inside a queryCASE WHEN score > 0.9 THEN 'pass' ELSE 'fail' END
DISTINCTDrop duplicate rowsSELECT DISTINCT model FROM evals
INSERT / UPDATE / DELETEWrite data (always with WHERE!)UPDATE evals SET score = 0.95 WHERE id = 42
CREATE INDEXSpeed up filtered/joined columnsCREATE INDEX ON evals (model)
EXPLAINShow the query planEXPLAIN ANALYZE SELECT …
How to practice: you don't need to install anything — SQLBolt and SQLZoo run in the browser. When you want a real database locally, use SQLite (zero setup) or DuckDB (great for CSV/parquet analytics), then graduate to Postgres — it's what production AI stacks (and pgvector) run on.

Reference Guide

Practice resources — verified & free

Same rules as the Resources page: every link checked live, each with a job to do.

Interactive · 18 lessons

SQLBolt

The best first contact with SQL: bite-size interactive lessons that run entirely in the browser.

Best for: your first 2–3 hours of SQL

Interactive · Classic

SQLZoo

Step-by-step tutorials with live exercises on real datasets — a natural follow-up to SQLBolt.

Best for: drilling SELECT/JOIN basics

Postgres Practice

PostgreSQL Exercises

One realistic dataset, ~80 graded problems from basic to window functions — with explanations.

Best for: going from "knows syntax" to "fluent"

Interview Prep

DataLemur

Real SQL interview questions from FAANG-style screens, with a free tier and instant feedback.

Best for: the week before interviews

Free Course · Hands-on

Kaggle — Intro to SQL

Query real public datasets (BigQuery) in hosted notebooks; pairs with their Advanced SQL follow-up.

Best for: SQL on big, real data

Tutorial · Analysis-focused

SQL Tutorial (formerly Mode)

The much-loved Mode analytics tutorial, now hosted by ThoughtSpot — strong on aggregation and window functions.

Best for: analytics-style SQL (evals, metrics)

Deep Reference

PostgreSQL Tutorial

The former postgresqltutorial.com — every Postgres feature explained with runnable examples.

Best for: looking things up while building

Quick Reference

W3Schools SQL

Fast syntax lookups with a try-it-yourself editor. Not deep, but always the quickest answer.

Best for: "what was the syntax again?"