Skip to content
Everyone-Website
Cheat sheet

SQL Cheat Sheet: Essential Queries and Commands

A practical SQL cheat sheet covering SELECT, WHERE, JOINs, aggregates, GROUP BY, INSERT, UPDATE, DELETE, and table basics — with copy-ready code examples.

Updated 6 June 2026 6 min read

A quick reference for the SQL you reach for every day. Examples use standard ANSI SQL and run on PostgreSQL, MySQL, SQL Server, SQLite, and Oracle unless a dialect note says otherwise.

SELECT Basics

SELECT reads rows from a table. Name the columns you want, or use * to grab them all.

-- Specific columns
SELECT first_name, last_name FROM users;

-- Every column (handy for exploring, avoid in production code)
SELECT * FROM users;

Rename a column in the output with AS. Use DISTINCT to collapse duplicate rows down to unique values.

-- Column aliases (AS is optional but clearer)
SELECT first_name AS name, email AS contact FROM users;

-- Unique values only
SELECT DISTINCT country FROM users;

Filtering with WHERE

WHERE keeps only the rows that match a condition. Combine conditions with AND, OR, and NOT.

OperatorMeaning
=Equal to
<> or !=Not equal to
< >Less than / greater than
<= >=Less than or equal / greater than or equal
SELECT * FROM products WHERE price > 100;
SELECT * FROM products WHERE category = 'books' AND price < 20;
SELECT * FROM users WHERE NOT country = 'US';

Match a set of values with IN, a range with BETWEEN, and a text pattern with LIKE.

-- Any value in a list
SELECT * FROM users WHERE country IN ('US', 'CA', 'MX');

-- Inclusive range (both ends count)
SELECT * FROM products WHERE price BETWEEN 10 AND 50;

-- Pattern matching: % = any number of chars, _ = exactly one char
SELECT * FROM users WHERE email LIKE '%@gmail.com';
SELECT * FROM users WHERE phone LIKE '555-___-____';

NULL means “unknown,” so it never equals anything — not even another NULL. Test for it with IS NULL / IS NOT NULL, never = NULL.

SELECT * FROM users WHERE phone IS NULL;
SELECT * FROM users WHERE phone IS NOT NULL;

Sorting and Limiting

ORDER BY sorts the result. Default is ascending (ASC); use DESC for largest/newest first. LIMIT caps the number of rows returned.

SELECT * FROM products ORDER BY price DESC;
SELECT * FROM products ORDER BY category ASC, price DESC;

-- First 10 rows (PostgreSQL, MySQL, SQLite)
SELECT * FROM products ORDER BY price DESC LIMIT 10;

Row-limiting syntax differs by database:

DatabaseSyntax
PostgreSQL / MySQL / SQLiteLIMIT 10
SQL ServerSELECT TOP 10 ...
OracleFETCH FIRST 10 ROWS ONLY
-- SQL Server
SELECT TOP 10 * FROM products ORDER BY price DESC;

-- Oracle (also valid on modern PostgreSQL)
SELECT * FROM products ORDER BY price DESC FETCH FIRST 10 ROWS ONLY;

Aggregate Functions

Aggregates collapse many rows into a single value.

FunctionReturns
COUNT()Number of rows
SUM()Total of a numeric column
AVG()Average value
MIN()Smallest value
MAX()Largest value
SELECT COUNT(*) FROM orders;
SELECT SUM(amount) FROM orders;
SELECT AVG(price), MIN(price), MAX(price) FROM products;

COUNT(*) counts every row; COUNT(column) counts only rows where that column is not NULL.

Grouping with GROUP BY and HAVING

GROUP BY splits rows into buckets so aggregates run per group. HAVING then filters those groups.

-- One row per country, with its order count
SELECT country, COUNT(*) AS order_count
FROM orders
GROUP BY country;

-- Only keep countries with more than 100 orders
SELECT country, COUNT(*) AS order_count
FROM orders
GROUP BY country
HAVING COUNT(*) > 100;

The difference: WHERE filters individual rows before grouping, while HAVING filters groups after aggregation. You cannot use an aggregate like COUNT() in WHERE.

-- WHERE filters rows first, HAVING filters the grouped result
SELECT country, AVG(amount) AS avg_amount
FROM orders
WHERE status = 'paid'
GROUP BY country
HAVING AVG(amount) > 50;

Joins

Joins combine rows from two tables based on a matching condition in the ON clause.

Join typeReturns
INNER JOINOnly rows with a match in both tables
LEFT JOINAll left rows, plus matches (NULLs where none)
RIGHT JOINAll right rows, plus matches (NULLs where none)
FULL OUTER JOINAll rows from both, matched where possible
-- Customers and their orders (only customers who ordered)
SELECT users.name, orders.amount
FROM users
INNER JOIN orders ON orders.user_id = users.id;

-- All users, even those with no orders (amount is NULL for them)
SELECT users.name, orders.amount
FROM users
LEFT JOIN orders ON orders.user_id = users.id;

Note: MySQL does not support FULL OUTER JOIN directly — emulate it by UNION-ing a LEFT JOIN and a RIGHT JOIN.

Modifying Data

Add new rows with INSERT INTO. List the columns, then the matching values.

INSERT INTO users (first_name, last_name, email)
VALUES ('Ada', 'Lovelace', 'ada@example.com');

-- Insert several rows at once
INSERT INTO users (first_name, email) VALUES
  ('Grace', 'grace@example.com'),
  ('Alan', 'alan@example.com');

UPDATE changes existing rows; DELETE FROM removes them. Always include a WHERE clause — without one, you change or delete every row in the table.

-- Update one user
UPDATE users SET email = 'ada.l@example.com' WHERE id = 1;

-- Delete one user
DELETE FROM users WHERE id = 42;
-- DANGER: no WHERE — this wipes or overwrites the ENTIRE table
UPDATE users SET active = false;
DELETE FROM users;

Table Basics

CREATE TABLE defines a new table, its columns, and their data types. A PRIMARY KEY uniquely identifies each row.

Data typeStores
INTWhole numbers
VARCHAR(n)Variable-length text up to n chars
DATECalendar dates
BOOLEAN / BOOLTrue / false
CREATE TABLE users (
  id         INT PRIMARY KEY,
  first_name VARCHAR(50),
  last_name  VARCHAR(50),
  email      VARCHAR(255),
  signup_date DATE,
  active     BOOLEAN
);

Change a table’s structure with ALTER TABLE. Remove a table entirely with DROP TABLE (this deletes the data too).

ALTER TABLE users ADD COLUMN phone VARCHAR(20);
ALTER TABLE users DROP COLUMN phone;

DROP TABLE users;

Good-Practice Tips

  • Test your filter with SELECT first. Run SELECT * FROM t WHERE ... to confirm exactly which rows match before turning that same WHERE into an UPDATE or DELETE.
  • List columns explicitly. SELECT id, name and INSERT INTO t (a, b) keep your queries stable when someone adds or reorders columns later. Reserve SELECT * for quick exploration.
  • Mind NULLs. Comparisons against NULL yield “unknown,” not true, so they silently drop rows. Use IS NULL, and remember COUNT(column) skips NULLs while COUNT(*) does not.
  • Wrap multi-statement changes in a transaction (BEGIN; ... COMMIT;) so you can ROLLBACK if something looks wrong.

Want more references like this? Browse our other developer guides for cheat sheets and tutorials.