SQL Cheat Sheet for Developers

·Updated Apr 4, 2026·
sqldatabasequery-languagesql cheat sheetsql referencedeveloper tools
·

Level: beginner · ~20 min read · Intent: informational

Audience: backend developers, data analysts, data engineers, technical teams, students, software engineers

Prerequisites

  • basic familiarity with databases
  • basic understanding of tables, rows, and columns

Key takeaways

  • A strong SQL cheat sheet should cover not just syntax, but also the query patterns developers use constantly, including joins, grouping, filtering, updates, inserts, and conditional logic.
  • The most useful SQL habit is understanding the flow of a query clearly: choose rows, filter rows, join related data, group or aggregate when needed, and only then sort or limit the result.

FAQ

What should a SQL cheat sheet include?
A good SQL cheat sheet should include core query syntax, filtering, joins, grouping, aggregates, CASE expressions, subqueries, CTEs, inserts, updates, deletes, and practical query patterns developers use regularly.
Is SQL syntax the same in every database?
The core SQL syntax is very similar across major databases, but some features, functions, date handling, limit syntax, upsert patterns, and advanced features differ between PostgreSQL, MySQL, SQL Server, SQLite, and others.
What are the most important SQL commands for developers?
The most important SQL commands for developers are SELECT, INSERT, UPDATE, DELETE, JOIN, GROUP BY, ORDER BY, CASE, COUNT, SUM, AVG, and common patterns like CTEs and subqueries.
What is the best way to learn SQL quickly?
The fastest way to learn SQL is to combine a cheat sheet with real table data and practical projects, then repeatedly write queries that use filtering, joins, grouping, and reporting logic.
0

SQL is one of the most useful tools a developer can know because it sits right at the boundary between application logic and data.

Whether you are building:

  • a backend API
  • a SaaS platform
  • a reporting dashboard
  • a BI workflow
  • an analytics pipeline
  • or an internal business tool

you will almost always run into SQL.

The problem is not that SQL is hard to start. The problem is that once you move past basic SELECT statements, there are a lot of patterns to remember:

  • filtering
  • joins
  • grouping
  • aggregates
  • conditional logic
  • updates
  • deletes
  • subqueries
  • CTEs
  • and database-specific differences

That is why a practical SQL cheat sheet is useful.

This article is designed to be a high-value reference you can actually use while working. It covers the syntax and patterns developers use most often, with examples that are simple enough to scan quickly but realistic enough to matter.

How to use this SQL cheat sheet

This cheat sheet is organized around everyday developer tasks.

That means it is less about theoretical SQL categories and more about questions like:

  • how do I select only the columns I need?
  • how do I join two tables?
  • how do I count rows by category?
  • how do I update records safely?
  • how do I write a CTE?
  • how do I use CASE?
  • how do I remove duplicates?
  • how do I inspect query performance?

The examples are written in generally portable SQL where possible. But remember:

Not all SQL dialects are identical.

The core ideas are consistent across:

  • PostgreSQL
  • MySQL
  • SQL Server
  • SQLite
  • MariaDB
  • Oracle

But some syntax differs, especially for:

  • limit and pagination
  • date functions
  • string functions
  • upsert behavior
  • JSON support
  • and advanced analytical features

So treat this as a practical cross-database developer guide, then adjust for your engine where needed.

The most important SQL rule for developers

Before the syntax, remember this:

A good SQL query is not just valid. It is clear, targeted, and shaped around the data you actually need.

That means good SQL usually does this:

  • selects only the needed columns
  • filters early
  • joins only what is necessary
  • groups only when useful
  • and avoids doing more work than required

That one mindset improves both:

  • correctness
  • and performance

A lot of bad SQL is not bad because it is illegal. It is bad because it is vague, wasteful, or hard to reason about later.

Basic SELECT syntax

The most fundamental query is SELECT.

Select all columns

SELECT *
FROM users;

Use this carefully. It is convenient, but in real applications it often returns more data than needed.

Select specific columns

SELECT id, email, created_at
FROM users;

This is usually better than SELECT * because it:

  • reduces data transfer
  • makes the query intent clearer
  • and can improve performance in real systems

Rename columns with aliases

SELECT
    id,
    email AS user_email,
    created_at AS signup_date
FROM users;

Aliases are useful when:

  • you want clearer output
  • you need readable report columns
  • or the original column names are not ideal in the result set

Filtering with WHERE

WHERE filters rows before they are returned.

Basic equality

SELECT *
FROM users
WHERE country = 'South Africa';

Greater than / less than

SELECT *
FROM orders
WHERE total_amount > 100;

Combine conditions with AND

SELECT *
FROM users
WHERE country = 'South Africa'
  AND is_active = true;

Combine conditions with OR

SELECT *
FROM users
WHERE country = 'South Africa'
   OR country = 'Namibia';

Use parentheses for clarity

SELECT *
FROM users
WHERE is_active = true
  AND (country = 'South Africa' OR country = 'Namibia');

Always use parentheses when a mixed AND / OR condition could be misread.

Useful WHERE patterns

IN

SELECT *
FROM users
WHERE country IN ('South Africa', 'Namibia', 'Botswana');

BETWEEN

SELECT *
FROM orders
WHERE total_amount BETWEEN 100 AND 500;

LIKE

SELECT *
FROM users
WHERE email LIKE '%@gmail.com';

Common patterns:

  • %text% contains
  • text% starts with
  • %text ends with

IS NULL

SELECT *
FROM users
WHERE phone_number IS NULL;

IS NOT NULL

SELECT *
FROM users
WHERE phone_number IS NOT NULL;

Important: never use = NULL. Use IS NULL.

Sorting with ORDER BY

Ascending sort

SELECT *
FROM products
ORDER BY price ASC;

Descending sort

SELECT *
FROM products
ORDER BY price DESC;

Sort by multiple columns

SELECT *
FROM orders
ORDER BY status ASC, created_at DESC;

This means:

  • sort by status first
  • then by newest within each status group

Limiting results

Different databases vary slightly here, but the common idea is to limit how many rows you return.

LIMIT

SELECT *
FROM posts
ORDER BY created_at DESC
LIMIT 10;

This is common in:

  • PostgreSQL
  • MySQL
  • SQLite

OFFSET

SELECT *
FROM posts
ORDER BY created_at DESC
LIMIT 10 OFFSET 20;

This gives:

  • 10 rows
  • after skipping the first 20

Useful for pagination, but large offsets can become expensive on big tables.

DISTINCT

Use DISTINCT when you want unique values.

Distinct one column

SELECT DISTINCT country
FROM users;

Distinct combinations

SELECT DISTINCT country, city
FROM users;

This returns unique country-city combinations.

SQL comments

Single-line comment

-- This query gets active users
SELECT *
FROM users
WHERE is_active = true;

Multi-line comment

/*
This query summarizes
monthly revenue
*/
SELECT *
FROM orders;

Comments matter because SQL often becomes much easier to maintain when business logic is explained.

JOINs

JOINs combine data from related tables.

They are one of the most important SQL skills.

Suppose you have:

  • customers
  • orders

and orders.customer_id links to customers.customer_id.

INNER JOIN

Returns only rows that match in both tables.

SELECT
    o.order_id,
    c.customer_name,
    o.total_amount
FROM orders o
INNER JOIN customers c
    ON o.customer_id = c.customer_id;

This is the most common join type.

LEFT JOIN

Returns all rows from the left table, even if there is no match on the right.

SELECT
    c.customer_name,
    o.order_id
FROM customers c
LEFT JOIN orders o
    ON c.customer_id = o.customer_id;

This is useful when you want:

  • all customers
  • including those with no orders

RIGHT JOIN

Less common in many codebases, but conceptually the reverse of LEFT JOIN.

SELECT
    c.customer_name,
    o.order_id
FROM customers c
RIGHT JOIN orders o
    ON c.customer_id = o.customer_id;

Many developers prefer rewriting RIGHT JOIN as LEFT JOIN for readability.

FULL OUTER JOIN

Returns matching rows plus unmatched rows from both sides.

SELECT
    c.customer_name,
    o.order_id
FROM customers c
FULL OUTER JOIN orders o
    ON c.customer_id = o.customer_id;

Supported in some databases, not all.

Common join pattern

A very common application query looks like this:

SELECT
    o.order_id,
    o.created_at,
    c.customer_name,
    c.email
FROM orders o
JOIN customers c
    ON o.customer_id = c.customer_id
WHERE o.status = 'Paid'
ORDER BY o.created_at DESC;

That is the kind of query developers write constantly.

Aggregate functions

Aggregate functions summarize data.

The most common ones are:

  • COUNT
  • SUM
  • AVG
  • MIN
  • MAX

COUNT all rows

SELECT COUNT(*)
FROM orders;

COUNT non-null values

SELECT COUNT(email)
FROM users;

SUM

SELECT SUM(total_amount)
FROM orders;

AVG

SELECT AVG(total_amount)
FROM orders;

MIN and MAX

SELECT MIN(price), MAX(price)
FROM products;

GROUP BY

Use GROUP BY when you want aggregates per category or per entity.

Count orders by customer

SELECT
    customer_id,
    COUNT(*) AS order_count
FROM orders
GROUP BY customer_id;

Revenue by month

SELECT
    order_month,
    SUM(total_amount) AS total_revenue
FROM monthly_orders
GROUP BY order_month;

Average salary by department

SELECT
    department_id,
    AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id;

HAVING

Use HAVING to filter grouped results after aggregation.

Customers with more than five orders

SELECT
    customer_id,
    COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) > 5;

Remember:

  • WHERE filters rows before grouping
  • HAVING filters groups after aggregation

CASE WHEN

CASE adds conditional logic.

Basic categorization

SELECT
    customer_id,
    total_spend,
    CASE
        WHEN total_spend >= 5000 THEN 'VIP'
        WHEN total_spend >= 1000 THEN 'Regular'
        ELSE 'Basic'
    END AS customer_segment
FROM customers;

Conditional aggregation

SELECT
    SUM(CASE WHEN status = 'Paid' THEN 1 ELSE 0 END) AS paid_orders,
    SUM(CASE WHEN status = 'Refunded' THEN 1 ELSE 0 END) AS refunded_orders
FROM orders;

This is one of the most useful SQL reporting patterns.

Subqueries

A subquery is a query inside another query.

Simple subquery in WHERE

SELECT *
FROM customers
WHERE customer_id IN (
    SELECT customer_id
    FROM orders
    WHERE total_amount > 1000
);

This returns customers who placed high-value orders.

Scalar subquery

SELECT *
FROM products
WHERE price > (
    SELECT AVG(price)
    FROM products
);

This returns products priced above the average.

Common Table Expressions (CTEs)

CTEs use WITH and are very useful for readability.

Basic CTE

WITH high_value_orders AS (
    SELECT *
    FROM orders
    WHERE total_amount > 1000
)
SELECT *
FROM high_value_orders;

CTE with aggregation

WITH customer_revenue AS (
    SELECT
        customer_id,
        SUM(total_amount) AS total_revenue
    FROM orders
    GROUP BY customer_id
)
SELECT *
FROM customer_revenue
WHERE total_revenue > 5000;

CTEs are especially useful when a query would otherwise become hard to read.

INSERT

Insert one row

INSERT INTO users (email, country, is_active)
VALUES ('alice@example.com', 'South Africa', true);

Insert multiple rows

INSERT INTO users (email, country, is_active)
VALUES
    ('alice@example.com', 'South Africa', true),
    ('bob@example.com', 'Namibia', true),
    ('cara@example.com', 'Botswana', false);

UPDATE

Update one or more rows

UPDATE users
SET is_active = false
WHERE last_login_at < '2025-01-01';

Always be careful with UPDATE.

Without a WHERE clause, it updates every row.

Update multiple columns

UPDATE products
SET price = 49.99,
    updated_at = CURRENT_TIMESTAMP
WHERE product_id = 10;

DELETE

Delete specific rows

DELETE FROM users
WHERE is_active = false;

Again, without WHERE, every row is deleted.

That is why delete safety matters.

TRUNCATE

TRUNCATE removes all rows from a table quickly.

TRUNCATE TABLE temp_import_data;

Use this carefully. It is not the same as a targeted delete.

CREATE TABLE

Basic table definition

CREATE TABLE customers (
    customer_id INT PRIMARY KEY,
    customer_name VARCHAR(255) NOT NULL,
    email VARCHAR(255),
    created_at TIMESTAMP
);

This defines:

  • a primary key
  • a required column with NOT NULL
  • normal text fields
  • a timestamp column

ALTER TABLE

Add a column

ALTER TABLE customers
ADD phone_number VARCHAR(50);

Rename a column

ALTER TABLE customers
RENAME COLUMN phone_number TO mobile_number;

Add a constraint

ALTER TABLE customers
ADD CONSTRAINT uq_customers_email UNIQUE (email);

DROP TABLE

DROP TABLE customers;

Use carefully. This removes the table definition itself, not just the rows.

Primary keys and unique constraints

Primary key

A primary key uniquely identifies each row.

CREATE TABLE products (
    product_id INT PRIMARY KEY,
    product_name VARCHAR(255) NOT NULL
);

Unique constraint

Prevents duplicate values in a column or column combination.

CREATE TABLE users (
    user_id INT PRIMARY KEY,
    email VARCHAR(255) UNIQUE
);

This is important for data integrity.

Basic index syntax

Indexes help queries find rows more efficiently.

Create an index

CREATE INDEX idx_orders_customer_id
ON orders (customer_id);

Composite index

CREATE INDEX idx_orders_customer_status_created
ON orders (customer_id, status, created_at);

Composite indexes are often very important for real application queries.

Finding duplicates

Find duplicate emails

SELECT
    email,
    COUNT(*) AS duplicate_count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

Preview duplicate rows with ROW_NUMBER

WITH ranked_rows AS (
    SELECT
        id,
        email,
        ROW_NUMBER() OVER (
            PARTITION BY email
            ORDER BY created_at ASC
        ) AS rn
    FROM users
)
SELECT *
FROM ranked_rows
WHERE rn > 1;

This is one of the most useful data-cleanup patterns in SQL.

Window functions

Window functions are more advanced, but extremely useful.

ROW_NUMBER

SELECT
    employee_id,
    department_id,
    salary,
    ROW_NUMBER() OVER (
        PARTITION BY department_id
        ORDER BY salary DESC
    ) AS salary_rank
FROM employees;

This assigns a ranking within each department.

Running total

SELECT
    order_date,
    total_amount,
    SUM(total_amount) OVER (
        ORDER BY order_date
    ) AS running_revenue
FROM daily_orders;

This is useful for dashboards and cumulative metrics.

EXISTS

EXISTS checks whether related rows exist.

SELECT *
FROM customers c
WHERE EXISTS (
    SELECT 1
    FROM orders o
    WHERE o.customer_id = c.customer_id
);

This returns customers who have at least one order.

This is often cleaner than some IN patterns in real SQL work.

UNION

UNION combines results from two queries.

UNION removes duplicates

SELECT email
FROM customers
UNION
SELECT email
FROM employees;

UNION ALL keeps duplicates

SELECT email
FROM customers
UNION ALL
SELECT email
FROM employees;

Use UNION ALL when you do not need duplicate removal. It is often faster and more predictable.

Common date query patterns

Date logic varies by database, but the general ideas are common.

Rows from the last 7 days

SELECT *
FROM orders
WHERE created_at >= CURRENT_DATE - INTERVAL '7 days';

Filter by year or month

Exact syntax differs across engines, but the idea is to avoid unnecessarily wrapping indexed date columns in functions when performance matters.

A better range pattern is often:

SELECT *
FROM orders
WHERE created_at >= '2026-04-01'
  AND created_at < '2026-05-01';

This is often clearer and more index-friendly than function-heavy date extraction in hot queries.

Useful string functions

Function names vary slightly by database, but these patterns are common.

Concatenate strings

SELECT first_name || ' ' || last_name AS full_name
FROM users;

Some databases use CONCAT(...) instead.

Lowercase

SELECT LOWER(email)
FROM users;

Uppercase

SELECT UPPER(country)
FROM users;

Trim spaces

SELECT TRIM(email)
FROM users;

These are useful in cleanup and normalization work.

Null handling with COALESCE

COALESCE returns the first non-null value.

SELECT
    customer_name,
    COALESCE(phone_number, 'No Phone') AS phone_display
FROM customers;

This is one of the most practical SQL functions because null values are everywhere.

Safe query habits for developers

A cheat sheet is not just syntax. It should also reinforce good habits.

1. Avoid SELECT *

Select only the columns you need.

2. Always think about WHERE

A missing filter can turn a safe query into a very expensive one.

3. Be careful with UPDATE and DELETE

Always confirm the WHERE clause.

A safe workflow is:

  • run a SELECT with the same filter first
  • verify the rows
  • then run the UPDATE or DELETE

4. Use aliases for readability

Especially in joined queries.

5. Inspect real execution plans when performance matters

SQL that looks fine can still perform badly.

6. Use constraints to protect data quality

Do not rely only on application code for uniqueness and integrity.

Common SQL query structure

A useful mental model for reading and writing queries is:

  1. SELECT
  2. FROM
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. HAVING
  7. ORDER BY
  8. LIMIT

That is not always the literal execution order inside the engine, but it is a very useful writing and reading model for developers.

A few common real-world query patterns

Get latest 10 records

SELECT id, created_at, status
FROM orders
ORDER BY created_at DESC
LIMIT 10;
SELECT c.*
FROM customers c
LEFT JOIN orders o
    ON c.customer_id = o.customer_id
WHERE o.order_id IS NULL;

This finds customers with no orders.

Top 5 customers by revenue

SELECT
    customer_id,
    SUM(total_amount) AS total_revenue
FROM orders
GROUP BY customer_id
ORDER BY total_revenue DESC
LIMIT 5;

Count rows by category

SELECT
    status,
    COUNT(*) AS status_count
FROM tickets
GROUP BY status
ORDER BY status_count DESC;

Update rows based on a rule

UPDATE products
SET stock_status =
    CASE
        WHEN stock_quantity = 0 THEN 'Out of Stock'
        WHEN stock_quantity < 10 THEN 'Low Stock'
        ELSE 'In Stock'
    END;

Find duplicate values

SELECT
    email,
    COUNT(*) AS duplicate_count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

SQL patterns worth memorizing

If you only memorize a few SQL patterns, make them these:

Filter rows

SELECT ...
FROM ...
WHERE ...;
SELECT ...
FROM a
JOIN b ON ...;

Aggregate by group

SELECT group_col, COUNT(*)
FROM table_name
GROUP BY group_col;

Filter grouped results

SELECT ...
FROM ...
GROUP BY ...
HAVING ...;

Conditional labeling

CASE
    WHEN ... THEN ...
    ELSE ...
END

Reusable CTE

WITH cte_name AS (
    SELECT ...
)
SELECT ...
FROM cte_name;

These patterns cover a huge amount of practical SQL work.

FAQ

What should a SQL cheat sheet include?

A good SQL cheat sheet should include core query syntax, filtering, joins, grouping, aggregates, CASE expressions, subqueries, CTEs, inserts, updates, deletes, and practical query patterns developers use regularly.

Is SQL syntax the same in every database?

The core SQL syntax is very similar across major databases, but some features, functions, date handling, limit syntax, upsert patterns, and advanced features differ between PostgreSQL, MySQL, SQL Server, SQLite, and others.

What are the most important SQL commands for developers?

The most important SQL commands for developers are SELECT, INSERT, UPDATE, DELETE, JOIN, GROUP BY, ORDER BY, CASE, COUNT, SUM, AVG, and common patterns like CTEs and subqueries.

What is the best way to learn SQL quickly?

The fastest way to learn SQL is to combine a cheat sheet with real table data and practical projects, then repeatedly write queries that use filtering, joins, grouping, and reporting logic.

Final thoughts

The best SQL cheat sheet is not one that lists every keyword in the language. It is one that helps developers do real work faster.

That means remembering the patterns that show up constantly:

  • selecting the right data
  • filtering clearly
  • joining related tables
  • grouping and aggregating
  • writing conditional logic
  • updating safely
  • and thinking about performance when queries matter

If you keep coming back to this cheat sheet while building real queries, you will reinforce the parts of SQL that matter most in everyday development.

And that is where SQL really becomes useful: not as a list of commands, but as a practical tool for shaping, understanding, and working with real data.

SQL guides

Explore the connected SQL guides on fundamentals, joins, analytics, performance, interviews, and practical workflows.

Pillar guide

SQL Complete Guide for Beginners and Developers

A complete SQL guide for beginners and developers covering databases, tables, SELECT, WHERE, JOINs, GROUP BY, CASE, subqueries, CTEs, inserts, updates, deletes, indexes, and practical query patterns.

View all SQL guides →

Related posts