A SELECT statement retrieves data. The clauses are written in a specific order, but the database executes them in a different logical order.
SELECT ...
FROM ...
JOIN ... ON ...
WHERE ...
GROUP BY ...
HAVING ...
ORDER BY ...
LIMIT ...;
FROM / JOIN: Gathers and joins the tables.WHERE: Filters rows based on conditions.GROUP BY: Groups rows into summary rows.HAVING: Filters groups based on conditions.SELECT: Selects the final columns.ORDER BY: Sorts the final result set.LIMIT: Restricts the number of rows returned.SELECT first_name, last_name, email
FROM users
WHERE country = 'Canada' AND age > 25;
AND, OR: Combine multiple conditions.IN (...): Match any value in a list (e.g., country IN ('USA', 'Canada')).BETWEEN ... AND ...: Match a value within a range.LIKE: Simple pattern matching (e.g., email LIKE '%@gmail.com'). The % is a wildcard.IS NULL / IS NOT NULL: Check for empty values.SELECT users.name, orders.order_date
FROM users
INNER JOIN orders ON users.id = orders.user_id;
SELECT country, COUNT(id) AS user_count
FROM users
GROUP BY country
HAVING COUNT(id) > 10; -- 'HAVING' filters after grouping
Common aggregate functions: COUNT(), SUM(), AVG(), MIN(), MAX().
SELECT name, salary
FROM employees
ORDER BY salary DESC -- 'DESC' for descending, 'ASC' for ascending
LIMIT 10; -- Get the top 10 highest salaries
SELECT c.name, o.order_date
FROM customers AS c JOIN orders AS o ON c.id = o.customer_id;
WITH clause to break down complex queries into logical, readable steps.
WITH RegionalSales AS (
SELECT region, SUM(amount) as total_sales
FROM sales
GROUP BY region
)
SELECT * FROM RegionalSales WHERE total_sales > 1000;
Venn diagrams are a helpful way to understand how different JOINs work.
| JOIN Type | Description |
|---|---|
| INNER JOIN | Returns records that have matching values in both tables. (The intersection). |
| LEFT JOIN | Returns all records from the left table, and the matched records from the right table. The result is NULL from the right side if there is no match. |
| RIGHT JOIN | Returns all records from the right table, and the matched records from the left table. The result is NULL from the left side if there is no match. |
| FULL OUTER JOIN | Returns all records when there is a match in either the left or right table. (Not supported by all databases like MySQL). |
Goal: Get the names and total spending of the top 3 customers who have spent more than $1000 in total.
Tables: customers (id, name), orders (id, customer_id, amount)
SELECT
c.name,
SUM(o.amount) AS total_spent
FROM
customers AS c
INNER JOIN
orders AS o ON c.id = o.customer_id
GROUP BY
c.id, c.name -- Group by both ID and name
HAVING
SUM(o.amount) > 1000
ORDER BY
total_spent DESC
LIMIT 3;
Syntax error near '...'
Ambiguous column name 'id'
customers.id or c.id.JOIN condition is likely incorrect or missing. Ensure you are joining on the correct primary/foreign key relationship. Using SELECT DISTINCT can sometimes hide the problem, but it's better to fix the join.misuse of aggregate function or filtering on an aggregate doesn't work.
SUM() or COUNT() in the WHERE clause. Aggregates can only be filtered in the HAVING clause.