All posts
5 min read

SQL for Beginners: The Queries You Need to Understand Your App's Data

You don't need to become a database expert to read your own data. The handful of SQL queries — SELECT, WHERE, ORDER BY, COUNT, JOIN — that let you answer real questions about your app, plus the two commands to be very careful with.

databasesgetting startedno-codebeginner

Your app has a database full of users, orders, and whatever else it stores. At some point you'll want to answer a question the app doesn't show you: How many people signed up this week? Which customers haven't paid? What does this user's account actually contain?

That's what SQL is for. SQL (Structured Query Language) is how you ask a relational database questions — and a small amount of it goes a long way.

If "table," "row," and "column" are new, read What Is a Database? first.

Where to run SQL

  • Your database provider's dashboard — most managed databases (Supabase, Neon, and others) have an "SQL editor."
  • A database app like TablePlus, DBeaver, or pgAdmin, connected with your connection details.
  • Your AI coding agent — it can run queries for you and explain the results.

Practise on a development database, not your live one, until you're comfortable. Reading is safe; the commands at the end of this article aren't.

1. SELECT: show me data

SELECT * FROM users;

"Show every column (*) of every row in the users table." On a big table, add a limit:

SELECT * FROM users LIMIT 10;

Pick specific columns:

SELECT name, email FROM users LIMIT 10;

2. WHERE: only the rows I want

SELECT name, email FROM users WHERE plan = 'pro';

Text goes in single quotes. You can combine conditions:

SELECT * FROM orders
WHERE status = 'paid' AND total > 50;

Useful comparisons:

  • =, !=, >, <, >=, <=
  • LIKE '%gmail.com' — text matching (% means "anything")
  • IS NULL / IS NOT NULL — empty or not (you can't use = NULL)
  • IN ('paid', 'refunded') — any of these values

Dates work too:

SELECT * FROM users WHERE created_at >= '2026-09-01';

3. ORDER BY: sort it

SELECT name, created_at FROM users
ORDER BY created_at DESC
LIMIT 20;

The 20 newest users. DESC is newest/largest first; ASC (the default) is oldest/smallest first.

4. COUNT and friends: summarise

SELECT COUNT(*) FROM users;

How many users? Other summaries:

SELECT SUM(total) FROM orders WHERE status = 'paid';   -- total revenue
SELECT AVG(total) FROM orders;                         -- average order
SELECT MAX(created_at) FROM orders;                    -- most recent order

5. GROUP BY: summarise per category

SELECT status, COUNT(*)
FROM orders
GROUP BY status;

Result:

status count
paid 412
refunded 9
pending 23

Signups per day:

SELECT DATE(created_at) AS day, COUNT(*)
FROM users
GROUP BY day
ORDER BY day DESC;

6. JOIN: combine tables

Tables link to each other — an order has a user_id pointing to a user. JOIN puts them together:

SELECT users.email, orders.total, orders.status
FROM orders
JOIN users ON orders.user_id = users.id
WHERE orders.status = 'pending';

"For each pending order, show the customer's email and the order total." That ON line is the connection: the order's user_id matches the user's id.

Joins are the most powerful part of SQL and the one that takes a little practice. Asking an AI to write a join for your question — and explain it — is a great way to learn.

Reading a table's structure

To see what columns a table has, most dashboards show it visually. In PostgreSQL's command-line tool, \d users describes the users table.

The two commands to respect

Everything above only reads. These change data:

UPDATE users SET plan = 'pro' WHERE id = 42;
DELETE FROM orders WHERE id = 1017;

The danger: forgetting the WHERE.

UPDATE users SET plan = 'pro';     -- every user is now pro
DELETE FROM orders;                -- every order is gone

There's no "are you sure?" and no undo. Before running any UPDATE or DELETE:

  1. Run it as a SELECT first with the same WHERE, to see exactly which rows it will affect.
  2. Make sure there's a recent backup. (How to Back Up a Postgres Database.)
  3. Prefer doing it on a development database first.
  4. Never let an AI agent run these against your live database without you reviewing them. (How to Stop an AI Agent From Deleting Your Production Database.)

(And DROP TABLE, which deletes a whole table — even more so.)

Let the AI write it, but read it

A great workflow for beginners: describe your question in plain English, ask your AI tool for the SQL, and ask it to explain the query line by line before you run it. You'll pick up SQL quickly — and you'll catch the occasional query that doesn't ask what you meant.

Write a SQL query that shows each customer's email and how much they've spent in total on paid orders, highest first. Explain each line.

The cheat sheet

SELECT cols FROM table            -- show data
WHERE condition                   -- filter rows
ORDER BY col DESC                 -- sort
LIMIT 10                          -- only the first 10
COUNT(*), SUM(x), AVG(x)          -- summarise
GROUP BY col                      -- summarise per category
JOIN other ON a.id = other.a_id   -- combine tables

UPDATE / DELETE ... WHERE ...     -- changes data: SELECT first, back up first

EasySpawn gives each project a managed PostgreSQL database with daily backups, and Claude Code can run and explain queries against your development data for you. See how it works or join the waitlist.

Related: What Is a Database? · What Are Database Migrations? · SQL Injection Explained

Keep reading