SELECT *
FROM users;Good for quick exploration, but prefer explicit columns in production queries.
Core SQL syntax and patterns for querying, filtering, sorting, joining, grouping, and modifying data.
Foundational read queries.
SELECT *
FROM users;Good for quick exploration, but prefer explicit columns in production queries.
SELECT id, email, created_at
FROM users;Selecting fewer columns often improves readability and can reduce I/O.
SELECT DISTINCT country
FROM customers;DISTINCT applies to the full selected column combination.
SELECT first_name AS given_name, last_name AS family_name
FROM users;Aliases are especially useful in reports and computed expressions.
Project computed values directly in the result set.
SELECT order_id, subtotal, tax, subtotal + tax AS total
FROM orders;Most SQL engines allow arithmetic, string, and function expressions in SELECT.
WHERE clause patterns.
SELECT *
FROM users
WHERE status = 'active';Use WHERE to limit the result set before grouping or ordering.
SELECT *
FROM invoices
WHERE amount > 1000
AND due_date < CURRENT_DATE;Combine predicates with AND and OR to express complex filters.
SELECT *
FROM products
WHERE category IN ('books', 'games', 'toys');IN is often clearer than multiple OR comparisons.
SELECT *
FROM events
WHERE created_at BETWEEN DATE "2025-01-01" AND DATE "2025-01-31";BETWEEN is inclusive on both ends in standard SQL.
SELECT *
FROM customers
WHERE email LIKE '%@example.com';Use % for any-length wildcard and _ for a single character.
SELECT *
FROM tasks
WHERE completed_at IS NULL;Use IS NULL or IS NOT NULL, not = NULL.
ORDER BY, LIMIT, FETCH, OFFSET patterns.
SELECT id, created_at
FROM orders
ORDER BY created_at DESC, id ASC;ORDER BY is applied after filtering and grouping.
SELECT *
FROM logs
ORDER BY created_at DESC
LIMIT 50;LIMIT is widely supported, though standard SQL also supports FETCH FIRST.
Skip rows and return a page-sized result set.
SELECT *
FROM posts
ORDER BY published_at DESC
LIMIT 20 OFFSET 40;Offset pagination is simple but can be slower for large offsets.
SELECT *
FROM employees
ORDER BY salary DESC
FETCH FIRST 10 ROWS ONLY;Supported in many modern SQL engines and part of the SQL standard.
Combine rows from multiple tables.
SELECT o.order_id, c.name
FROM orders o
JOIN customers c ON c.customer_id = o.customer_id;INNER JOIN returns only matched rows.
Keep all rows from the left table and match rows from the right table.
SELECT c.customer_id, o.order_id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.customer_id;Rows without a match on the right side get NULLs for right-side columns.
SELECT e.employee_id, d.department_name
FROM employees e
RIGHT JOIN departments d ON d.department_id = e.department_id;Many teams prefer rewriting RIGHT JOIN as LEFT JOIN for consistency.
SELECT a.id AS a_id, b.id AS b_id
FROM a
FULL OUTER JOIN b ON b.id = a.id;Useful for reconciliation queries.
SELECT e.employee_id, e.name, m.name AS manager_name
FROM employees e
LEFT JOIN employees m ON m.employee_id = e.manager_id;Self joins are common in hierarchical or parent-child tables.
SELECT c.color, s.size
FROM colors c
CROSS JOIN sizes s;Cross joins multiply rows, so use them deliberately.
Summaries and grouped queries.
SELECT COUNT(*) AS row_count
FROM users;COUNT(*) includes rows regardless of NULL values.
SELECT status, COUNT(*) AS total
FROM orders
GROUP BY status;All non-aggregated selected columns must appear in GROUP BY.
SELECT country, status, COUNT(*) AS total
FROM customers
GROUP BY country, status;Useful for reports sliced by multiple categories.
SELECT customer_id, COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) >= 5;WHERE filters rows before grouping; HAVING filters grouped results.
SELECT
COUNT(*) AS total_rows,
SUM(amount) AS total_amount,
AVG(amount) AS avg_amount,
MIN(amount) AS min_amount,
MAX(amount) AS max_amount
FROM payments;Most SQL engines support these core aggregate functions.