Skip to main content
Back to SQL Coding

SQL Coding · Cheat Sheet

Doing It With AI

Tip: Use your browser's print function (Ctrl+P / Cmd+P) to save as PDF for offline study.

Cheatsheet: Doing It With AI

One page for Topic 4. AI-generated SQL is syntactically confident and logically fallible in the exact same ways as human SQL — and every expensive bug runs cleanly.


The AI-SQL audit checklist

Run this on every AI-generated (or any) query before its number goes anywhere:

#CheckQuestion to ask
1GrainOne row per what? Does the GROUP BY grain match the grain of the question asked?
2Fan-outDoes any join change the row count before an aggregate runs? A SUM after a many-row join is inflated
3Join type vs "all" languageQuestion says "all customers" but the query INNER JOINs to orders? Non-purchasers are already gone
4NULL handlingAnything AVGed/COUNTed where NULLs might hide? (AVG skips NULLs; NOT IN + NULL returns zero rows)
5Date boundariesBETWEEN on a timestamp column is guilty until proven innocent — look for half-open ranges (>= start AND < next_start)
6Alias vs computationAS active_users on a COUNT(*) over sessions is session volume wearing a users name — verify every business-metric alias against its expression
7Explanation vs schemaThe AI's prose is a claim about the code, not proof. Check the SQL does what the description says, against the actual tables

Then two sanity checks:

  • COUNT first. Run the skeleton as SELECT COUNT(*) before the full query. Expecting ~6 rows (one per month) and getting 4,000 means the grain is wrong — stop before anyone sees a number.
  • Check one known answer. Pick a slice where the truth is already trusted (finance's signed-off month, one customer you know). Right on the known case → trust rises sharply; wrong → bug found for the price of one lookup.

The spec template for directing AI

Formula: business question + output grain + decisions already made.

ProvideExampleWhy it matters
Table schemas with typesorders(order_id, customer_id, order_total numeric, created_at timestamptz)Types matter — timestamptz is why BETWEEN breaks
Sample rows (3 per table)Shows status = 'completed' vs 'COMPLETE', whether customer_id is ever NULLKills a whole category of wrong assumptions
The grain of each table"One row in orders is one checkout; one row in sessions is one visit"The single highest-value sentence — disarms fan-out, wrong GROUP BY, sessions-as-users in advance
Expected ballpark"~50k customers, ~$2M/month"Lets you instantly reject an $11M result
Edge cases / definitions"Gross revenue, ignore refunds; half-open date ranges; Jan–Jun 2026"Removes the dozen valid interpretations of "show me revenue"

Bad ask: "Show me revenue." Good ask: "Monthly gross revenue (sum of order_total, ignore refunds) for Jan–Jun 2026, one row per month, using half-open date ranges."

Reporting a bug back

Name mechanism + consequence + intent — never "it looks wrong":

  • "This INNER JOIN to orders drops customers with no orders — I need all customers, so LEFT JOIN from customers."
  • "BETWEEN on created_at (a timestamp) cuts off most of the last day — use >= start AND < next-day."
  • "This counts sessions, not users — I need COUNT(DISTINCT customer_id)."

AI is extremely good at applying a fix once the defect is named, and near-useless at guessing what displeased you.


Query-plan reading: the whole syllabus

EXPLAIN shows how the database will run a query; EXPLAIN ANALYZE runs it and adds actuals. You need to recognize exactly three patterns:

PatternWhat it looks likeMeaning
Full scan of a huge table for a narrow questionSeq Scan on events/orders when the query wants 12 rowsMissing or unusable index — engineer-fixable in minutes
Estimate wildly off actualrows=210 estimated vs rows=8412047 actualPlanner is flying blind (stale statistics); every downstream decision suspect. 10x is unremarkable; 1,000x+ is the finding
Nested loop over millions of rowsNested Loop above steps producing millions"For each of 5M rows, search side B" — why the query runs for an hour

Calibration:

  • Seq scan on a small table, or when the query needs most of the table: fine. "Seq scan bad" is wrong often enough to be dangerous.
  • cost is an abstract score, not seconds — only comparable between plans.
  • Your job is triage, not tuning: quote the pattern specifically ("seq scan on events, 210 estimated vs 8.4M actual, feeding a nested loop") and hand it to an engineer.
  • An AI saying "this query is efficient" is a guess about a database it has never seen. The plan is the ground truth.

The dashboard-audit workflow

The capstone method, transferable to any query that decides something:

  1. State the question and expected output grain first — how many rows should come back, one row per what?
  2. Audit each CTE/subquery separately — what is one row, and does any join change row count before an aggregate? (Fan-out before SUM = inflation.)
  3. Audit every date filter — BETWEEN on a timestamp is guilty until proven innocent.
  4. Audit every alias against its expression — especially business-metric names (active_users, revenue, conversion_rate).
  5. Check derived ratios last — a ratio of two unaudited numbers compounds both errors.
  6. Run the sanity checks — COUNT comparison, plus one known-answer slice against a number someone already trusts.
  7. Report by mechanism, consequence, intent — that's what turns an audit into a one-round fix.

The three highest-yield questions on any dashboard query: did a join change row count before an aggregate, is BETWEEN sitting on a timestamp, and does each alias match its expression.


Traps

  • Verifying by re-asking the same AI "is this correct?" — it confidently affirms its own work. Verify against the data, not against more prose.
  • Accepting "runs without errors" as correct — every expensive bug in this track executes cleanly; syntax errors are the only ones the database catches.
  • Skipping the audit because the query looks like the last one that was fine — one changed join or date filter reintroduces everything.
  • Not specifying the output grain in the ask — the AI picks one, and you discover which during the audit.
  • Treating plan cost as time, or demanding indexes everywhere — indexes slow every write; "add an index" is not your call.
  • Trusting an AI's performance claims over the actual plan.
  • Being the only reviewer on high-stakes numbers — anything feeding a board deck or a pricing decision gets a second human reviewer. That's policy, not doubt.

Aligned to the PostgreSQL documentation and standard SQL semantics.

Make this cheat sheet yours

Personalize this sheet — focus it however you study, or build one from the exact questions you keep getting wrong.

Sign up free to create a personalized cheat sheet.