← Back to list

How I Stopped Writing Bad Queries and Built SQL Systems That Actually Scale

From messy SELECT statements to production-grade data pipelines.

Ford Lucas in Write A Catalyst · 2026-03-22 16:20 · 27 claps · 3.4 min read paywalled
#sql #sql-server #sql-tutorial #sql-tips
Open on Medium ↗
Wiki topics: 🔧 · Data Engineering

How I Stopped Writing Bad Queries and Built SQL Systems That Actually Scale

From messy SELECT statements to production-grade data pipelines.

Image by author

Image by author

For a long time, I thought I knew SQL.

I could write joins, filters, even some window functions. But every time the data got bigger or the logic got complex, my queries started breaking down — slow, unreadable, and impossible to debug.

The real shift happened when I stopped treating SQL as a query language… and started treating it as a system design tool.

This is how I now approach SQL after years of building real-world data systems.

1) I Stopped Writing One Big Query (And Everything Got Better)

Beginners write one giant query.

Experienced developers break logic into layers.

Instead of doing everything at once, I now use Common Table Expressions (CTEs) to structure my thinking.

WITH raw_orders AS (
    SELECT *
    FROM orders
    WHERE order_date >= '2025-01-01'
),

cleaned_orders AS (
    SELECT
        order_id,
        customer_id,
        CAST(order_date AS DATE) AS order_date,
        revenue
    FROM raw_orders
    WHERE revenue IS NOT NULL
),

aggregated_orders AS (
    SELECT
        customer_id,
        COUNT(*) AS total_orders,
        SUM(revenue) AS total_revenue
    FROM cleaned_orders
    GROUP BY customer_id
)

SELECT *
FROM aggregated_orders
ORDER BY total_revenue DESC;

Now each step:

  • has a clear purpose
  • is debuggable
  • is reusable

This alone eliminated most of my SQL headaches.

2) Window Functions Replaced Half My Business Logic

There was a time I used subqueries for everything.

Then I discovered window functions — and they completely changed how I write SQL.

SELECT
    customer_id,
    order_id,
    order_date,
    revenue,
    SUM(revenue) OVER (PARTITION BY customer_id ORDER BY order_date) AS running_total,
    RANK() OVER (PARTITION BY customer_id ORDER BY revenue DESC) AS revenue_rank
FROM orders;

This allows me to:

  • track cumulative metrics
  • rank within groups
  • compare rows without collapsing data

Once you understand window functions, SQL starts feeling less like querying and more like analysis.

3) I Designed Tables for Queries, Not Storage

One mistake I made early on was designing tables like a database engineer.

Now I design them like a data analyst.

That means:

  • denormalizing when needed
  • optimizing for read performance
  • thinking about query patterns first
CREATE TABLE customer_summary AS
SELECT
    c.customer_id,
    c.name,
    COUNT(o.order_id) AS total_orders,
    SUM(o.revenue) AS total_revenue,
    MAX(o.order_date) AS last_order_date
FROM customers c
LEFT JOIN orders o
ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.name;

This kind of table:

  • removes repeated joins
  • speeds up dashboards
  • simplifies downstream queries

4) Indexing Changed Everything About Performance

At some point, my queries became correct… but painfully slow.

That’s when I learned SQL performance isn’t just about writing queries — it’s about how the database executes them.

CREATE INDEX idx_orders_customer_id
ON orders(customer_id);

CREATE INDEX idx_orders_order_date
ON orders(order_date);

Now:

  • filters run faster
  • joins become efficient
  • large datasets become manageable

Ignoring indexes is like writing Python without caring about time complexity.

5) I Started Thinking in Pipelines, Not Queries

Instead of writing one-off queries, I now build SQL pipelines.

Each step transforms data and feeds into the next.

-- Step 1: Extract
CREATE TABLE stage_orders AS
SELECT * FROM raw_orders_source;

-- Step 2: Transform
CREATE TABLE cleaned_orders AS
SELECT
    order_id,
    customer_id,
    revenue
FROM stage_orders
WHERE revenue > 0;

-- Step 3: Aggregate
CREATE TABLE metrics AS
SELECT
    customer_id,
    SUM(revenue) AS total_revenue
FROM cleaned_orders
GROUP BY customer_id;

This approach:

  • makes workflows repeatable
  • reduces errors
  • creates production-ready systems

6) Debugging SQL Became a Skill on Its Own

SQL errors are rarely obvious.

So I built a habit: test every layer independently.

-- Debug step-by-step
SELECT * FROM raw_orders LIMIT 10;

SELECT * FROM cleaned_orders WHERE revenue IS NULL;

SELECT customer_id, COUNT(*)
FROM aggregated_orders
GROUP BY customer_id
HAVING COUNT(*) > 1;

Instead of guessing, I:

  • isolate problems
  • validate assumptions
  • test edge cases

This turned debugging from frustration into a process.

7) Automation Took My SQL to Another Level

The biggest upgrade wasn’t writing better queries.

It was running them automatically.

-- Example for scheduled refresh
CREATE OR REPLACE TABLE daily_metrics AS
SELECT
    CURRENT_DATE AS run_date,
    customer_id,
    SUM(revenue) AS daily_revenue
FROM orders
WHERE order_date = CURRENT_DATE
GROUP BY customer_id;

Combined with schedulers:

  • pipelines run daily
  • reports update automatically
  • systems stay consistent

At this point, SQL stops being a tool and becomes infrastructure.

8) I Learned to Write SQL That Other People Can Read

Readable SQL is underrated.

Messy queries slow teams down more than bad logic.

So I follow simple rules:

  • consistent indentation
  • meaningful aliases
  • clear naming
SELECT
    o.customer_id,
    COUNT(o.order_id) AS total_orders,
    SUM(o.revenue) AS total_revenue
FROM orders AS o
GROUP BY o.customer_id
ORDER BY total_revenue DESC;

Clean SQL scales across teams.

Final Shift That Changed Everything

Early on, I thought SQL was about retrieving data.

Now I see it differently.

SQL is about shaping data into something useful — reliably, repeatedly, and efficiently.

Once you start thinking this way, your queries stop being temporary solutions… and start becoming systems.


메타데이터
post_id
35f6d0cb05d1
slug
how-i-stopped-writing-bad-queries-and-built-sql-systems-that-actually-scale-35f6d0cb05d1
url
https://medium.com/write-a-catalyst/how-i-stopped-writing-bad-queries-and-built-sql-systems-that-actually-scale-35f6d0cb05d1
canonical_url
https://medium.com/write-a-catalyst/how-i-stopped-writing-bad-queries-and-built-sql-systems-that-actually-scale-35f6d0cb05d1
author_url
https://medium.com/@fordlucas125
status
ok
fetched_at
2026-06-09 15:37:30