SwadhyAI Notes

All SQL notes

🧪Query patterns and debugging

Bisect the multiset

Debug SQL like distributed systems: reproduce on a tiny schema, compare row counts at each CTE stage, then add locks and plans when timing is “random.” Multisets lie, duplicates before an aggregate are the usual villain.

SQL

Stage counts inside CTEs

WITH filtered AS (
  SELECT * FROM orders WHERE status = 'OPEN'
),
joined AS (
  SELECT f.order_id, c.segment
  FROM filtered f
  JOIN customers c USING (customer_id)
)
SELECT 'filtered' AS stage, COUNT(*) FROM filtered
UNION ALL
SELECT 'joined', COUNT(*) FROM joined;
✓Illustrative result set
stagecount
filtered1200
joined1180

👃Smells

What to check first.

SmellCheck
Row multiplication after a joinFan-out: broken 1:1 assumption or missing key in ON.
Off-by-one time filtersHalf-open ranges [start, end); normalize time zones before compare.

Production shells

  • Iterative debugging on shared prod with destructive tries.
  • ORM logs missing bind parameters, cannot replay the plan.
  • Stopping at the first plan without estimated vs actual row comparison.

Fixtures and plans

  • Build a checklist: keys, NULLs, duplicates, time zones.
  • Use EXPLAIN (ANALYZE, BUFFERS) equivalents; snapshot CSV fixtures for CI.
  • Pair with lock graphs when CPU is idle but latency spikes.

Tickets

A ten-row schema that reproduces the bug beats paragraphs of prose, attach it to the ticket like you would a failing unit test.

TL;DR

Debug SQL by freezing inputs (parameters, isolation, session settings), capturing the plan and row counts at each stage, and shrinking to a minimal repro. Common fixes: wrong join grain, NULL logic, missing index for filter/sort, stale statistics, or an ORM-generated N+1. Treat suspicious results as data model bugs until proven otherwise.