1. Introduction: What is SQL?
SQL stands for Structured Query Language. It is the global standard programming language designed specifically for managing, querying, and manipulating data stored within a relational database management system (RDBMS). Whether you are interacting with MySQL, PostgreSQL, SQL Server, Oracle, or SQLite, the core language structure remains uniform.
To effectively learn SQL, you must understand that databases are structured into tables containing rows and columns. SQL queries allow you to run declarative commands to fetch exact datasets, perform data analytics, update existing information, or securely alter structural schemas.
β° Table of Contents
18 sectionsπ Getting Started
π§© SQL Core
β‘ Functions & Grouping
π Advanced SQL
π Database
π Final Reference
SQL Quick Reference
| Command | Description | Example |
|---|---|---|
| SELECT DQL | Retrieves data from a database table. |
|
| WHERE DQL | Filters records based on specified conditions. |
|
| ORDER BY DQL | Sorts the result-set in ascending or descending order. |
|
| GROUP BY DQL | Groups rows that have the same values into summary rows. |
|
| HAVING DQL | Filters groups created by the GROUP BY clause based on conditions. |
|
| DISTINCT DQL | Returns only distinct (different) values from columns. |
|
| LIMIT DQL | Specifies the maximum number of rows the query should return. |
|
| INSERT DML | Inserts new data records into a table. |
|
| UPDATE DML | Modifies existing data records within a table. |
|
| DELETE DML | Deletes specific records from a table based on a condition. |
|
| UNION DML | Combines the result-set of two or more SELECT statements. |
Why use an SQL cheat sheet?
Relational databases contain complex syntactical combinations. Even seasoned developers often reference structural documentation to verify exact keyword order or constraint definitions. An SQL cheat sheet bridges the gap between conceptual understanding and real-time execution by mapping out production-ready database commands in a single, scannable index.
SQL Operators Cheat Sheet
SQL operators are used to filter, compare, and combine data within SQL queries. Understanding these operators is essential for writing efficient and readable SQL statements.
Arithmetic Operators
Arithmetic operators perform mathematical calculations on numeric values.
| Operator | Meaning | Example | Explanation |
|---|---|---|---|
| + | Addition |
|
Adds two numeric values together. |
| - | Subtraction |
|
Subtracts one value from another. |
| * | Multiplication |
|
Multiplies two numeric values. |
| / | Division |
|
Divides one numeric value by another. |
| % | Modulo |
|
Returns the remainder after division. |
Comparison Operators
Comparison operators compare two values and return true or false.
| Operator | Meaning | Example | Explanation |
|---|---|---|---|
| = | Equal to |
|
Finds rows where a value matches exactly. |
| <> | Not equal to |
|
Finds rows where a value is different. |
| != | Not equal to |
|
Alternative syntax for not equal in many databases. |
| > | Greater than |
|
Returns rows with values greater than a number. |
| < | Less than |
|
Returns rows with values less than a number. |
| >= | Greater than or equal to |
|
Includes values equal to or above the condition. |
| <= | Less than or equal to |
|
Includes values equal to or below the condition. |
Logical Operators
Logical operators combine or modify conditions in a SQL query.
| Operator | Meaning | Example | Explanation |
|---|---|---|---|
| AND | Both conditions must be true |
|
Returns rows that match all conditions. |
| OR | At least one condition must be true |
|
Returns rows that match one or more conditions. |
| NOT | Negates a condition |
|
Returns rows where the condition is not true. |
| BETWEEN | Within a range |
|
Filters values inside a specified range. |
| IN | Matches any value in a list |
|
Cleaner alternative to multiple OR conditions. |
| LIKE | Pattern matching |
|
Finds text values matching a pattern. |
| EXISTS | Checks if a subquery returns rows |
|
Useful for checking related records. |
| ANY | Compares against any subquery value |
|
Returns true if the comparison matches at least one value. |
| ALL | Compares against all subquery values |
|
Returns true only if the comparison matches every value. |
NULL Operators
NULL operators check whether a value is missing or unknown.
| Operator | Meaning | Example | Explanation |
|---|---|---|---|
| IS NULL | Value is missing |
|
Finds rows where a column has no value. |
| IS NOT NULL | Value exists |
|
Finds rows where a column contains a value. |
Set Operators
Set operators combine the results of two or more SELECT statements.
| Operator | Meaning | Example | Explanation |
|---|---|---|---|
| UNION | Combines unique rows |
|
Combines results and removes duplicates. |
| UNION ALL | Combines all rows |
|
Combines results and keeps duplicates. |
| INTERSECT | Returns matching rows from both queries |
|
Returns only rows found in both result sets. |
| EXCEPT | Returns rows from first query only |
|
Returns rows from the first query that do not exist in the second query. |
Logical Operators
SQL Logical Operators allow you to combine, exclude, and evaluate multiple conditions within a query. They are most commonly used with the WHERE, HAVING, and JOIN clauses to build powerful filtering logic.
By using logical operators correctly, you can retrieve more accurate results, improve query readability, and write cleaner SQL statements. Whether you're filtering customers from multiple countries, checking salary ranges, or combining several search conditions, logical operators are an essential part of everyday SQL development.
π‘ What You'll Learn
This guide covers the most commonly used SQL logical operators, including AND, OR, NOT, BETWEEN, IN, LIKE, EXISTS, ANY, and ALL. You'll also learn operator precedence, best practices, common mistakes, and practical examples that you can immediately use in your own SQL queries.
AND Operator
The AND operator combines two or more conditions in a SQL query. A row is returned only if every condition evaluates to TRUE. It is one of the most frequently used logical operators when filtering data with the WHERE clause.
| Syntax | Description | Returns |
|---|---|---|
| condition1 AND condition2 | Combines multiple conditions. | Rows where every condition is true. |
SELECT *
FROM employees
WHERE department = 'Sales'
AND salary > 50000;
OR Operator
The OR operator combines two or more conditions and returns rows when at least one condition evaluates to TRUE. It is commonly used when you want to search for multiple possible values within the same query.
| Syntax | Description | Returns |
|---|---|---|
| condition1 OR condition2 | Checks multiple conditions. | Rows where one or more conditions are true. |
SELECT *
FROM customers
WHERE country = 'Sweden'
OR country = 'Norway';
NOT Operator
The NOT operator reverses a condition in SQL. It returns rows where the specified condition is not true. It is commonly used with WHERE, IN, LIKE, BETWEEN, and NULL checks.
| Syntax | Description | Returns |
|---|---|---|
| NOT condition | Reverses the result of a condition. | Rows where the condition is false. |
SELECT *
FROM products
WHERE NOT category = 'Electronics';
BETWEEN Operator
The BETWEEN operator filters values within a specified range. It can be used with numbers, dates, and text values. One important thing to remember is that BETWEEN is inclusive, meaning both the starting and ending values are included in the results.
| Syntax | Description | Returns |
|---|---|---|
| value BETWEEN min AND max | Filters values within a range. | Rows including both boundary values. |
SELECT *
FROM products
WHERE price BETWEEN 50 AND 100;
SELECT *
FROM employees
WHERE hire_date BETWEEN '2024-01-01'
AND '2024-12-31';
- Filter products within a price range.
- Find employees hired during a specific year.
- Return orders placed between two dates.
- Select IDs within a numeric interval.
IN Operator
The IN operator checks whether a value matches any value in a list. It provides a cleaner and more readable alternative to writing multiple OR conditions, especially when comparing the same column against several possible values.
| Syntax | Description | Returns |
|---|---|---|
| value IN (...) | Checks if a value exists in a list. | Rows matching any value in the list. |
SELECT *
FROM customers
WHERE country IN ('Sweden', 'Norway', 'Denmark');
IN vs Multiple OR Conditions
Instead of writing:
SELECT *
FROM customers
WHERE country = 'Sweden'
OR country = 'Norway'
OR country = 'Denmark';
You can simply write:
SELECT *
FROM customers
WHERE country IN ('Sweden', 'Norway', 'Denmark');
LIKE Operator
The LIKE operator is used to search for a specific pattern in a text column. It is commonly used with wildcard characters such as % and _ to find values that start with, end with, or contain certain characters.
| Wildcard | Meaning | Example Pattern | Matches |
|---|---|---|---|
| % | Any number of characters | 'A%' | Values starting with A |
| % | Any number of characters | '%son' | Values ending with son |
| % | Any number of characters | '%book%' | Values containing book |
| _ | Exactly one character | '_ohn' | John, Rohn, Sohn |
SELECT *
FROM customers
WHERE name LIKE 'A%';
LIKE 'A%'
Finds values that begin with the letter A.
LIKE '%son'
Finds values that end with the text βsonβ.
LIKE '%book%'
Finds values that contain the word βbookβ.
LIKE '_ohn'
Finds four-letter values ending in βohnβ.
SELECT *
FROM products
WHERE product_name LIKE '%laptop%';
EXISTS Operator
The EXISTS operator checks whether a subquery returns one or more rows. If the subquery returns any result, the EXISTS condition evaluates to TRUE. It is commonly used to test relationships between tables without returning duplicate records.
| Syntax | Description | Returns |
|---|---|---|
| EXISTS (subquery) | Checks whether a subquery returns any rows. | TRUE if at least one row exists. |
SELECT *
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);
- Check if related records exist
- Find customers with orders
- Find products with sales
- Validate relationships between tables
ANY Operator
The ANY operator compares a value against the results of a subquery. The condition is considered TRUE if it matches at least one value returned by the subquery. It is typically used together with comparison operators such as >, <, =, or <>.
| Syntax | Description | Returns |
|---|---|---|
| value > ANY (subquery) | Compares a value with any value returned by a subquery. | TRUE if at least one comparison succeeds. |
SELECT *
FROM products
WHERE price > ANY (
SELECT price
FROM products
WHERE category = 'Books'
);
- Compare against a dynamic list of values.
- Find values greater than at least one result.
- Filter data using subqueries.
- Create flexible comparison logic.
ALL Operator
The ALL operator compares a value against every value returned by a subquery. The condition is considered TRUE only if the comparison is true for all values in the subquery result. It is commonly used with comparison operators such as >, <, =, and <>.
| Syntax | Description | Returns |
|---|---|---|
| value > ALL (subquery) | Compares a value with every value returned by a subquery. | TRUE only if every comparison succeeds. |
SELECT *
FROM products
WHERE price > ALL (
SELECT price
FROM products
WHERE category = 'Books'
);
Operator Precedence
SQL evaluates logical operators in a specific order. This is called operator precedence. Understanding this order is important because queries that mix AND, OR, and NOT can return different results than expected if parentheses are not used.
| Priority | Operator | Meaning |
|---|---|---|
| 1 | NOT | Evaluated first |
| 2 | AND | Evaluated after NOT |
| 3 | OR | Evaluated last |
SELECT *
FROM customers
WHERE age > 18
OR country = 'USA'
AND active = 1;
SELECT *
FROM customers
WHERE age > 18
OR (country = 'USA' AND active = 1);
SELECT *
FROM customers
WHERE (age > 18 OR country = 'USA')
AND active = 1;
Common Logical Operator Mistakes
Logical operators are powerful, but small mistakes can completely change your SQL results. The most common issues happen when mixing AND and OR, using NULL incorrectly, or choosing the wrong operator for a list or range.
1. Mixing AND and OR Without Parentheses
β BadSELECT *
FROM customers
WHERE age > 18
OR country = 'USA'
AND active = 1;
SELECT *
FROM customers
WHERE (age > 18 OR country = 'USA')
AND active = 1;
Use parentheses to make your logic clear and prevent unexpected results.
2. Using = NULL Instead of IS NULL
β BadSELECT *
FROM customers
WHERE phone = NULL;
SELECT *
FROM customers
WHERE phone IS NULL;
NULL means an unknown or missing value. Use IS NULL or IS NOT NULL instead of equality operators.
3. Using Too Many OR Conditions Instead of IN
β BadSELECT *
FROM products
WHERE category = 'Books'
OR category = 'Games'
OR category = 'Software';
SELECT *
FROM products
WHERE category IN ('Books', 'Games', 'Software');
Use IN when checking one column against multiple possible values.
Logical Operator Best Practices
Use logical operators carefully to keep your SQL queries accurate, readable, and easy to maintain. These best practices help prevent common filtering mistakes and make complex conditions easier to understand.
Use Parentheses for Clarity
When combining AND and OR, always use parentheses to make the intended logic clear.
Use IN for Multiple Values
Use IN instead of repeating many OR conditions against the same column.
Use BETWEEN for Ranges
Use BETWEEN for readable range filters, but remember that it includes both boundary values.
Handle NULL Correctly
Use IS NULL and IS NOT NULL. Do not compare NULL values with = or !=.
Keep Conditions Readable
Break complex WHERE clauses across multiple lines so they are easier to scan, debug, and update.
Avoid Unnecessary NOT
Use positive conditions when possible. Queries with too many NOT operators can be harder to understand.
SQL Query Execution Order
Did you know that SQL queries do not run in the order they are written? Databases execute clauses in a specific sequence to optimize performance and properly filter data. Understanding this order is essential for writing efficient queries and debugging complex behavior like alias visibility.
| Order | Clause | What Happens |
|---|---|---|
| 1 | FROM |
The database identifies the target tables and processes any JOIN sub-clauses to gather the raw data. |
| 2 | WHERE |
Filters the base rows according to specific conditions before any grouping or aggregation takes place. |
| 3 | GROUP BY |
Collapses the filtered rows into distinct groups based on shared values in the specified columns. |
| 4 | HAVING |
Filters the grouped rows. Unlike WHERE, this clause can evaluate aggregate functions like SUM() or COUNT(). |
| 5 | SELECT |
Computes expressions, applies column aliases, and extracts the final columns to be returned. This is where DISTINCT is also processed. |
| 6 | ORDER BY |
Sorts the final result set in ascending or descending order. Column aliases created in the SELECT step are available here. |
| 7 | LIMIT / OFFSET |
Discards rows outside the specified range, restricting the final output to a precise maximum number of rows. |
SQL Query Execution Order
SQL queries are written in one order but executed in another. Understanding the execution order helps explain why aliases cannot always be used in WHERE clauses and why GROUP BY behaves the way it does.
| Order | Clause | Description |
|---|---|---|
| 1 | FROM |
Selects the source table(s) |
| 2 | JOIN |
Combines related tables |
| 3 | WHERE |
Filters rows before grouping |
| 4 | GROUP BY |
Groups rows |
| 5 | HAVING |
Filters grouped data |
| 6 | SELECT |
Returns selected columns |
| 7 | DISTINCT |
Removes duplicate rows |
| 8 | ORDER BY |
Sorts the result |
| 9 | LIMIT / OFFSET |
Limits returned rows |
π‘ Remember
Although SELECT appears first in a query, SQL actually executes FROM before SELECT. This is one of the most common concepts beginners misunderstand.
SQL Data Types
SQL data types define the kind of values that can be stored in a database column. Choosing the correct data type helps improve storage efficiency, query performance, and data accuracy while ensuring your database behaves as expected.
Every table column must have a data type. Whether you're storing numbers, text, dates, or binary data, selecting the right type is one of the most important decisions in database design.
Numeric Data Types
Numeric data types store numbers such as IDs, quantities, prices, ratings, measurements, and financial values. Choosing the right numeric type helps reduce storage size and prevents rounding or precision problems.
| Data Type | Use Case | Example | Notes |
|---|---|---|---|
| INT | Whole numbers | age INT |
Common for IDs, counts, and quantities. |
| BIGINT | Very large whole numbers | views BIGINT |
Useful for large counters or high-volume systems. |
| DECIMAL(p,s) | Exact decimal values | price DECIMAL(10,2) |
Best choice for money and precise calculations. |
| FLOAT | Approximate decimal values | rating FLOAT |
Useful for scientific or approximate values. |
| DOUBLE | Higher precision approximate decimals | measurement DOUBLE |
More precision than FLOAT, but still approximate. |
CREATE TABLE products (
product_id INT,
product_name VARCHAR(100),
price DECIMAL(10,2),
stock_quantity INT,
rating FLOAT
);
String Data Types
String data types store text values such as names, emails, addresses, product titles, descriptions, and categories. Choosing the right string type helps control storage size, improve performance, and keep your database structure clean.
| Data Type | Use Case | Example | Notes |
|---|---|---|---|
| CHAR(n) | Fixed-length text | country_code CHAR(2) |
Best for values with a consistent length, such as country codes. |
| VARCHAR(n) | Variable-length text | email VARCHAR(255) |
Most common choice for names, emails, titles, and short text. |
| TEXT | Long text content | description TEXT |
Useful for descriptions, comments, articles, and longer content. |
| NCHAR(n) | Fixed-length Unicode text | language_code NCHAR(2) |
Used when Unicode support is needed for fixed-length values. |
| NVARCHAR(n) | Variable-length Unicode text | display_name NVARCHAR(100) |
Useful for multilingual text in databases that distinguish Unicode types. |
CREATE TABLE customers (
customer_id INT,
first_name VARCHAR(50),
last_name VARCHAR(50),
email VARCHAR(255),
country_code CHAR(2),
notes TEXT
);
Date & Time Data Types
Date and time data types store calendar dates, timestamps, and time values. They are commonly used for order dates, user registrations, appointments, event scheduling, logs, and audit records.
| Data Type | Use Case | Example | Notes |
|---|---|---|---|
| DATE | Store only a calendar date | birth_date DATE |
No time information is stored. |
| TIME | Store only a time value | start_time TIME |
Useful for schedules and opening hours. |
| DATETIME | Date and time together | created_at DATETIME |
Widely supported by MySQL and other databases. |
| TIMESTAMP | Automatic timestamps | updated_at TIMESTAMP |
Often updates automatically when a row changes. |
| YEAR | Store only a year | model_year YEAR |
Mainly supported by MySQL. |
CREATE TABLE orders (
order_id INT,
order_date DATE,
created_at DATETIME,
updated_at TIMESTAMP
);
SQL Constraints
SQL constraints are rules applied to table columns to enforce data integrity and ensure that only valid data is stored. They help prevent duplicate values, missing information, invalid relationships, and inconsistent records.
Constraints are typically defined when creating or modifying a table and play a crucial role in maintaining reliable, accurate, and consistent databases.
PRIMARY KEY Constraint
A PRIMARY KEY uniquely identifies each row in a table. Every table should have one primary key to ensure that each record can be referenced without ambiguity. A primary key cannot contain NULL values, and each value must be unique.
| Constraint | Purpose | Allows NULL? | Allows Duplicates? |
|---|---|---|---|
| PRIMARY KEY | Uniquely identifies each record | β No | β No |
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
first_name VARCHAR(50),
last_name VARCHAR(50)
);
FOREIGN KEY Constraint
A FOREIGN KEY creates a relationship between two database tables. It ensures that values in one table match existing values in another table, helping maintain referential integrity and preventing invalid relationships.
| Constraint | Purpose | References | Allows Duplicates? |
|---|---|---|---|
| FOREIGN KEY | Links related tables | Primary Key in another table | β Yes |
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
FOREIGN KEY (customer_id)
REFERENCES customers(customer_id)
);
UNIQUE Constraint
The UNIQUE constraint ensures that every value in a column (or combination of columns) is different. Unlike a PRIMARY KEY, a table can have multiple UNIQUE constraints, making it ideal for values such as email addresses, usernames, or product SKUs.
| Constraint | Purpose | Allows NULL? | Allows Duplicates? |
|---|---|---|---|
| UNIQUE | Prevents duplicate values | β Usually Yes* | β No |
CREATE TABLE users (
user_id INT PRIMARY KEY,
email VARCHAR(255) UNIQUE,
username VARCHAR(50) UNIQUE
);
NOT NULL Constraint
The NOT NULL constraint ensures that a column must always contain a value. It prevents missing or empty data in required fields.
| Constraint | Purpose |
|---|---|
| NOT NULL | Prevents NULL values. |
CREATE TABLE users (
user_id INT PRIMARY KEY,
email VARCHAR(255) NOT NULL,
first_name VARCHAR(50) NOT NULL
);
CHECK Constraint
The CHECK constraint limits the values that can be stored in a column. It is useful when a column should only accept values that meet a specific rule, such as a positive price, a valid age range, or a limited set of status values.
| Constraint | Purpose | Example Rule |
|---|---|---|
| CHECK | Validates column values. | price > 0 |
CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) CHECK (price > 0),
stock_quantity INT CHECK (stock_quantity >= 0)
);
DEFAULT Constraint
The DEFAULT constraint automatically assigns a predefined value when no value is provided during an INSERT operation. It helps ensure consistent data and reduces the need to specify common values manually.
| Constraint | Purpose | Example Value |
|---|---|---|
| DEFAULT | Automatically assigns a value. | DEFAULT 'Active' |
CREATE TABLE users (
user_id INT PRIMARY KEY,
username VARCHAR(50),
status VARCHAR(20) DEFAULT 'Active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
AUTO_INCREMENT / IDENTITY
AUTO_INCREMENT and IDENTITY are used to automatically generate a new numeric value for each inserted row. They are commonly used for primary key columns such as user IDs, order IDs, and product IDs.
| Database | Common Syntax | Purpose |
|---|---|---|
| MySQL | AUTO_INCREMENT |
Automatically generates increasing values. |
| SQL Server | IDENTITY(1,1) |
Starts at 1 and increases by 1. |
| PostgreSQL | GENERATED AS IDENTITY |
Modern standard identity column syntax. |
CREATE TABLE customers (
customer_id INT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL
);
Constraint Best Practices
Well-designed constraints help maintain data integrity, improve database consistency, and reduce application errors. The following recommendations represent common best practices used in production databases.
β Best Practices
- Use a PRIMARY KEY on every table.
- Use FOREIGN KEY constraints to maintain relationships.
- Apply NOT NULL to required columns.
- Use UNIQUE for emails, usernames, and other business identifiers.
- Use CHECK constraints to prevent invalid values.
- Use DEFAULT values for common initial data.
- Prefer auto-generated numeric primary keys when appropriate.
β Common Mistakes
- Using multiple primary keys instead of one primary key with additional UNIQUE constraints.
- Allowing NULL values in required columns.
- Creating relationships without foreign keys.
- Storing invalid values instead of enforcing CHECK constraints.
- Using business data such as email addresses as primary keys.
- Forgetting default values for frequently used columns.
- Relying only on application validation instead of database constraints.
Aggregate Functions
SQL aggregate functions perform calculations across multiple rows and return a single result. They are commonly used for totals, averages, counts, minimum values, maximum values, and summary reports.
| Function | Purpose | Example | Common Use Case |
|---|---|---|---|
| COUNT() | Counts rows or non-NULL values. | COUNT(*) |
Count users, orders, products, or records. |
| SUM() | Adds numeric values together. | SUM(total_amount) |
Calculate total sales or revenue. |
| AVG() | Returns the average value. | AVG(price) |
Find average prices, ratings, or scores. |
| MIN() | Returns the lowest value. | MIN(price) |
Find the cheapest product or earliest date. |
| MAX() | Returns the highest value. | MAX(price) |
Find the most expensive product or latest date. |
SELECT
COUNT(*) AS total_orders,
SUM(total_amount) AS total_revenue,
AVG(total_amount) AS average_order_value,
MIN(total_amount) AS smallest_order,
MAX(total_amount) AS largest_order
FROM orders;
COUNT(*) counts all rows. COUNT(column) only counts rows where that column is not NULL.
Aggregate functions become much more powerful when combined with GROUP BY to summarize data by category.
Most aggregate functions ignore NULL values, except COUNT(*), which counts every row.
GROUP BY & HAVING
GROUP BY groups rows that have the same values, while HAVING filters grouped results. They are commonly used together with aggregate functions like COUNT(), SUM(), and AVG().
| Clause | Purpose | Used With | Example |
|---|---|---|---|
| GROUP BY | Groups rows by one or more columns. | Aggregate functions | GROUP BY department |
| HAVING | Filters grouped results. | GROUP BY | HAVING COUNT(*) > 5 |
| WHERE | Filters rows before grouping. | SELECT queries | WHERE status = 'Paid' |
SELECT
customer_id,
COUNT(*) AS total_orders,
SUM(total_amount) AS total_spent
FROM orders
WHERE status = 'Paid'
GROUP BY customer_id
HAVING SUM(total_amount) > 1000
ORDER BY total_spent DESC;
WHERE filters rows before grouping. HAVING filters results after grouping.
Use GROUP BY to summarize sales, orders, users, categories, departments, or dates.
Columns in SELECT should usually be either grouped or aggregated.
String Functions
SQL string functions are used to clean, format, combine, and search text values. They are commonly used with names, emails, product titles, descriptions, categories, and other text-based columns.
| Function | Purpose | Example | Common Use Case |
|---|---|---|---|
| CONCAT() | Combines two or more text values. | CONCAT(first_name, ' ', last_name) |
Create full names or combined labels. |
| LOWER() | Converts text to lowercase. | LOWER(email) |
Normalize emails or search terms. |
| UPPER() | Converts text to uppercase. | UPPER(country_code) |
Format codes, labels, or abbreviations. |
| TRIM() | Removes leading and trailing spaces. | TRIM(username) |
Clean imported or user-entered data. |
| SUBSTRING() | Extracts part of a text value. | SUBSTRING(phone, 1, 3) |
Extract prefixes, codes, or text fragments. |
| LENGTH() | Returns the length of a text value. | LENGTH(password) |
Validate text length or find short values. |
| REPLACE() | Replaces part of a string. | REPLACE(phone, '-', '') |
Clean phone numbers or formatted text. |
SELECT
CONCAT(first_name, ' ', last_name) AS full_name,
LOWER(email) AS normalized_email,
TRIM(username) AS clean_username
FROM users;
Use TRIM(), LOWER(), and REPLACE() to clean inconsistent text values.
Use CONCAT(), UPPER(), and SUBSTRING() to format output for reports.
Some databases use slightly different names, such as LEN() instead of LENGTH().
Date Functions
SQL date functions make it easy to retrieve the current date, extract date parts, perform calculations, and filter records based on time. They are essential when working with orders, invoices, schedules, reports, and user activity.
| Function | Purpose | Example | Common Use |
|---|---|---|---|
| CURRENT_DATE | Returns today's date. | CURRENT_DATE |
Reports and filtering. |
| NOW() | Returns current date and time. | NOW() |
Timestamps and logging. |
| YEAR() | Extracts the year. | YEAR(order_date) |
Yearly reports. |
| MONTH() | Extracts the month. | MONTH(order_date) |
Monthly summaries. |
| DAY() | Extracts the day. | DAY(order_date) |
Daily reporting. |
| DATEDIFF() | Calculates the difference between dates. | DATEDIFF(end,start) |
Age, delivery time, project duration. |
SELECT
CURRENT_DATE,
NOW(),
YEAR(order_date) AS order_year,
MONTH(order_date) AS order_month,
DATEDIFF(ship_date, order_date) AS shipping_days
FROM orders;
Extract years, months, or days to build monthly and yearly reports.
Use DATEDIFF() to measure durations such as delivery times or customer retention.
Some databases use different function names and syntax for date calculations.
SQL JOIN Cheat Sheet
SQL JOINs are used to combine rows from two or more tables based on related columns. They are essential for working with relational databases, connecting customers to orders, products to categories, users to roles, and many other table relationships.
INNER JOIN
Returns only rows where both tables have matching values.
LEFT JOIN
Returns all rows from the left table and matching rows from the right table.
RIGHT JOIN
Returns all rows from the right table and matching rows from the left table.
FULL JOIN
Returns all rows from both tables, matched where possible.
CROSS JOIN
Returns every possible combination of rows from both tables.
SELF JOIN
Joins a table to itself, often used for hierarchies or comparisons.
| JOIN Type | Returns | Keeps Unmatched Rows? | Typical Use |
|---|---|---|---|
| INNER JOIN | Only matching rows from both tables. | β No | customers with matching orders |
| LEFT JOIN | All rows from the left table plus matching right rows. | β Left table | Find all customers, even those without orders. |
| RIGHT JOIN | All rows from the right table plus matching left rows. | β Right table | Less common; often replaceable with LEFT JOIN. |
| FULL OUTER JOIN | All rows from both tables. | β Both tables | Compare two datasets and find missing matches. |
| CROSS JOIN | Every row combination. | N/A | Create combinations, calendars, or matrix results. |
| SELF JOIN | Rows compared within the same table. | N/A | Employee-manager relationships or duplicate checks. |
SELECT
c.customer_id,
c.customer_name,
o.order_id,
o.order_date
FROM customers c
LEFT JOIN orders o
ON c.customer_id = o.customer_id;
Subqueries
A SQL subquery is a query placed inside another query. Subqueries are useful when you need to filter, compare, or calculate values based on results from another SELECT statement.
| Subquery Type | Where It Appears | Purpose | Example Pattern |
|---|---|---|---|
| WHERE Subquery | WHERE |
Filters rows using another query. | WHERE price > (SELECT AVG(price) ...) |
| IN Subquery | WHERE IN |
Matches values from another result set. | WHERE customer_id IN (...) |
| EXISTS Subquery | WHERE EXISTS |
Checks whether related rows exist. | WHERE EXISTS (SELECT 1 ...) |
| FROM Subquery | FROM |
Creates a temporary result table. | FROM (SELECT ...) AS summary |
SELECT
product_name,
price
FROM products
WHERE price > (
SELECT AVG(price)
FROM products
);
Use subqueries when a condition depends on another query result.
For complex logic, a CTE can often be easier to read than a nested subquery.
A subquery used with = should return one value. Use IN when it can return multiple values.
Common Table Expressions (CTE)
A Common Table Expression, or CTE, creates a temporary named result set that can be referenced inside a SQL query. CTEs are often used to make complex queries easier to read, organize, and maintain.
| Feature | Purpose | Syntax | Best Use |
|---|---|---|---|
| WITH | Starts a CTE. | WITH cte_name AS (...) |
Create a readable temporary result set. |
| Named Result | Gives the subquery a reusable name. | sales_summary |
Improve query readability. |
| Main Query | Uses the CTE result. | SELECT * FROM cte_name |
Filter, join, or aggregate the CTE output. |
WITH customer_totals AS (
SELECT
customer_id,
SUM(total_amount) AS total_spent
FROM orders
GROUP BY customer_id
)
SELECT
customer_id,
total_spent
FROM customer_totals
WHERE total_spent > 1000;
A CTE is often easier to read than a deeply nested subquery, especially when the logic has multiple steps.
Use CTEs for reports, summaries, filtering steps, and complex transformations.
A CTE only exists for the query that immediately follows it. It is not stored permanently like a table or view.
Window Functions
Window functions perform calculations across a set of related rows while keeping every individual row in the result. Unlike GROUP BY, they do not collapse rows into a single summary, making them ideal for rankings, running totals, moving averages, and comparisons.
| Function | Purpose | Example | Common Use |
|---|---|---|---|
| ROW_NUMBER() | Assigns a unique row number. | ROW_NUMBER() OVER(...) |
Pagination and ranking. |
| RANK() | Ranks rows with gaps. | RANK() OVER(...) |
Leaderboards. |
| DENSE_RANK() | Ranks rows without gaps. | DENSE_RANK() |
Competition rankings. |
| LAG() | Accesses the previous row. | LAG(price) |
Compare current vs previous values. |
| LEAD() | Accesses the next row. | LEAD(price) |
Forecasting and comparisons. |
| SUM() OVER() | Running total. | SUM(amount) OVER(...) |
Cumulative sales. |
SELECT
employee_name,
salary,
RANK() OVER (
ORDER BY salary DESC
) AS salary_rank
FROM employees;
Indexes
Indexes improve query performance by allowing the database to locate rows much faster. They are especially useful for columns that are frequently searched, filtered, sorted, or used in JOIN conditions.
| Index Type | Purpose | Example |
|---|---|---|
| Primary Index | Automatically created for PRIMARY KEY. | PRIMARY KEY (id) |
| Unique Index | Prevents duplicate values. | UNIQUE(email) |
| Regular Index | Speeds up searches. | INDEX(last_name) |
| Composite Index | Indexes multiple columns. | INDEX(last_name, first_name) |
CREATE INDEX idx_lastname
ON customers(last_name);
Database Objects & Transactions
Views and transactions are useful SQL features for organizing queries and protecting data changes. Views make complex queries reusable, while transactions help ensure that multiple database operations succeed or fail together.
Views
A view is a saved SQL query that behaves like a virtual table. Views are useful for simplifying complex queries, improving readability, and controlling what data users can access.
| Command | Purpose |
|---|---|
| CREATE VIEW | Create a reusable virtual table. |
| DROP VIEW | Remove an existing view. |
CREATE VIEW active_customers AS
SELECT customer_id, customer_name, email
FROM customers
WHERE status = 'Active';
Transactions
A transaction groups multiple SQL statements into one reliable unit. If something goes wrong, the changes can be rolled back to keep the database consistent.
| Command | Purpose |
|---|---|
| BEGIN | Start a transaction. |
| COMMIT | Save all changes. |
| ROLLBACK | Undo changes. |
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE account_id = 1;
UPDATE accounts
SET balance = balance + 100
WHERE account_id = 2;
COMMIT;
SELECT
The SELECT statement is the foundational backbone of data retrieval in SQL. It is used to query and extract specific columns of data from a database table.
Syntax:
SELECT column1, column2 FROM table_name;
Example:
SELECT first_name, email FROM employees;
When to use it: Use this command whenever you need to fetch specific fields from your database without altering the underlying data records.
WHERE
The WHERE clause is used to filter records horizontally. It ensures that only the rows that meet a specific logical condition are returned in the output data.
Syntax:
SELECT column_list FROM table_name WHERE condition;
Example:
SELECT product_name FROM products WHERE price > 50.00;
When to use it: Deploy this clause to isolate records based on structural rules, such as numerical boundaries, exact text strings, or dates.
JOIN
The JOIN clause is used to combine rows from two or more tables, based on a related column between them. This allows you to query normalized data across your relational database structures efficiently.
Syntax:
SELECT column_list
FROM table1
INNER JOIN table2
ON table1.common_column = table2.common_column;
Example:
The following query fetches orders along with the corresponding customer names by linking the customer ID present in both tables:
SELECT orders.order_id, customers.customer_name, orders.order_date
FROM orders
INNER JOIN customers
ON orders.customer_id = customers.customer_id;
GROUP BY
The GROUP BY statement groups rows that have the same values into summary rows. It is often used with aggregate functions like COUNT(), MAX(), MIN(), SUM(), and AVG() to arrange the result-set by one or more columns.
Syntax:
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE condition
GROUP BY column_name;
Example:
The following query finds the total number of employees working in each department across the organization:
SELECT department_id, COUNT(employee_id) AS total_employees
FROM employees
GROUP BY department_id;
ORDER BY
The ORDER BY keyword is used to sort the result-set in ascending or descending order. By default, queries sort records in ascending order (ASC). To sort the records in descending order, you must explicitly use the DESC keyword.
Syntax:
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 ASC|DESC, column2 ASC|DESC;
Example:
The following query selects all customers from the table, sorted alphabetically by their last name in descending order:
SELECT customer_id, first_name, last_name
FROM customers
ORDER BY last_name DESC;
HAVING
The HAVING clause was added to SQL because the WHERE keyword cannot be used with aggregate functions (like COUNT(), SUM(), or AVG()). It acts as a horizontal filter for groups created by the GROUP BY statement.
Syntax:
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE condition
GROUP BY column_name
HAVING aggregate_function(column_name) condition;
Example:
The following query lists the departments that have more than 5 employees, filtering out any smaller teams:
SELECT department_id, COUNT(employee_id) AS total_employees
FROM employees
GROUP BY department_id
HAVING COUNT(employee_id) > 5;
INSERT INTO
The INSERT INTO statement is used to insert new records into a table. You can either specify both the column names and the values to be inserted, or insert values for all columns in their default structural order.
Syntax:
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
Example:
The following query adds a brand new employee record into the employees table, filling out the specific fields:
INSERT INTO employees (first_name, last_name, email, hire_date)
VALUES ('Alice', 'Smith', 'alice.smith@example.com', '2026-07-02');
UPDATE
The UPDATE statement is used to modify the existing records in a table. Crucial Warning: Always be careful when updating records! If you omit the WHERE clause, all records in the entire table will be updated and overwritten.
Syntax:
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
Example:
The following query updates the email address and department for a specific employee whose unique ID is 101:
UPDATE employees
SET email = 'alice.new@example.com', department_id = 4
WHERE employee_id = 101;
DELETE
The DELETE statement is used to remove existing records from a table. Just like with the UPDATE statement, the WHERE clause is critical. If you forget the WHERE clause, all records in the table will be deleted permanently.
Syntax:
DELETE FROM table_name WHERE condition;
Example:
The following query deletes a specific record from the employees table where the employee ID matches 101:
DELETE FROM employees WHERE employee_id = 101;
Common SQL Mistakes
Even experienced SQL developers occasionally make mistakes that lead to incorrect results, poor performance, or difficult-to-maintain queries. Learning these common pitfalls will help you write cleaner, faster, and more reliable SQL.
β Forgetting the WHERE Clause
Running an UPDATE or DELETE statement without a WHERE clause affects every row in the table.
β Using SELECT *
Avoid selecting every column unless necessary. Retrieve only the columns you actually need to improve performance and readability.
β Ignoring NULL Values
Remember that = NULL never works. Use IS NULL or IS NOT NULL instead.
β Missing Indexes
Queries filtering or joining large tables without proper indexes can become extremely slow.
β Incorrect JOIN Conditions
Joining on the wrong column often creates duplicate rows or missing records. Always verify your JOIN keys.
β Mixing AND and OR
Always use parentheses when combining AND and OR to avoid unexpected logical results.
Download the SQL Cheat Sheet
We're currently creating a professionally formatted printable PDF version of this SQL Cheat Sheet. In the meantime, you can access the complete and always up-to-date reference directly on this page.