SQL Query Examples
Learn from real-world examples of common SQL mistakes, optimizations, and best practices. Click "Try This Example" to analyze any query in the analyzer.
SELECT * Performance Issue
Selecting all columns with * is inefficient. Only request the columns you need.
SELECT * FROM users WHERE id = 1SELECT id, name, email FROM users WHERE id = 1Missing WHERE in UPDATE
UPDATE without WHERE affects all rows. Always specify which rows to update.
UPDATE users SET status = 'active'UPDATE users SET status = 'active' WHERE id = 123Function in WHERE Clause
Functions on columns in WHERE prevent index usage. Move logic to the comparison value.
SELECT * FROM orders WHERE YEAR(order_date) = 2024SELECT id, total, order_date FROM orders WHERE order_date >= '2024-01-01' AND order_date < '2025-01-01'Cartesian Join
Missing join condition creates a Cartesian product, multiplying rows exponentially.
SELECT * FROM users, ordersSELECT u.id, u.name, o.total FROM users u JOIN orders o ON u.id = o.user_idN+1 Query Problem
Subqueries in SELECT execute for each row. Use JOINs with GROUP BY instead.
SELECT u.name, (SELECT COUNT(*) FROM orders WHERE user_id = u.id) as order_count FROM users uSELECT u.name, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.nameUnnecessary DISTINCT
DISTINCT on unique columns (like id) is redundant and adds overhead.
SELECT DISTINCT id, name FROM usersSELECT id, name FROM usersLIKE with Leading Wildcard
Leading wildcards in LIKE prevent index usage. Use full-text search for contains queries.
SELECT * FROM products WHERE name LIKE '%phone%'SELECT id, name, price FROM products WHERE name LIKE 'phone%'Subquery to JOIN Conversion
JOINs are typically faster than subqueries and more readable.
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE total > 100)SELECT DISTINCT u.id, u.name, u.email FROM users u JOIN orders o ON u.id = o.user_id WHERE o.total > 100Using EXISTS vs IN
EXISTS is more efficient than NOT IN and handles NULLs correctly.
SELECT * FROM users WHERE id NOT IN (SELECT user_id FROM orders)SELECT u.id, u.name, u.email FROM users u WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id)Proper Index Usage
Avoid functions on indexed columns. Use case-insensitive collation or functional indexes.
SELECT * FROM orders WHERE LOWER(email) = 'user@example.com'SELECT id, total, email FROM orders WHERE email = 'user@example.com'Query Refactoring with CTE
CTEs improve readability and can be optimized by the query planner.
SELECT * FROM (SELECT * FROM users WHERE status = 'active') AS active_users WHERE created_at > '2024-01-01'WITH active_users AS (SELECT id, name, email, created_at FROM users WHERE status = 'active') SELECT * FROM active_users WHERE created_at > '2024-01-01'Efficient Pagination
Keyset pagination is faster than OFFSET for large datasets.
SELECT * FROM products ORDER BY id OFFSET 10000 LIMIT 20SELECT id, name, price FROM products WHERE id > 10000 ORDER BY id LIMIT 20Proper JOIN Syntax
Use explicit JOIN syntax for clarity and to avoid accidental Cartesian products.
SELECT * FROM users u, orders o WHERE u.id = o.user_idSELECT u.id, u.name, o.total FROM users u INNER JOIN orders o ON u.id = o.user_idUsing CTEs Effectively
CTEs make complex queries more readable and maintainable.
SELECT u.name, o.total FROM users u JOIN (SELECT user_id, SUM(total) as total FROM orders GROUP BY user_id) o ON u.id = o.user_idWITH order_totals AS (SELECT user_id, SUM(total) as total FROM orders GROUP BY user_id) SELECT u.name, ot.total FROM users u JOIN order_totals ot ON u.id = ot.user_idWindow Functions
Window functions provide elegant solutions for analytical queries.
SELECT u.name, (SELECT COUNT(*) FROM orders o2 WHERE o2.user_id = u.id) FROM users uSELECT u.name, COUNT(o.id) OVER (PARTITION BY u.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_idBatch Operations
Batch inserts are much faster than individual INSERT statements.
INSERT INTO users (name) VALUES ('Alice'); INSERT INTO users (name) VALUES ('Bob'); INSERT INTO users (name) VALUES ('Charlie');INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie')Transaction Management
Use transactions to ensure data consistency for related operations.
UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2;BEGIN; UPDATE accounts SET balance = balance - 100 WHERE id = 1; UPDATE accounts SET balance = balance + 100 WHERE id = 2; COMMIT;N+1 Query Pattern
Correlated subquery executes once per row (N+1 problem). Use JOIN with GROUP BY instead.
SELECT u.name, (SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS total FROM users uSELECT u.name, COUNT(o.id) AS total FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.nameInvalid GROUP BY Clause
All non-aggregated columns in SELECT must be in GROUP BY clause.
SELECT cidade, nome, COUNT(*) FROM clientes GROUP BY cidadeSELECT cidade, nome, COUNT(*) FROM clientes GROUP BY cidade, nomeConvert Subquery to JOIN
Subqueries with IN are slower than JOINs. Rewrite for better performance.
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE status = 'paid')SELECT DISTINCT u.* FROM users u INNER JOIN orders o ON u.id = o.user_id WHERE o.status = 'paid'OR Prevents Index Usage
OR with different columns prevents index usage. Use UNION instead.
SELECT * FROM users WHERE cidade = 'SP' OR status = 'Ativo'SELECT * FROM users WHERE cidade = 'SP' UNION SELECT * FROM users WHERE status = 'Ativo'LIKE Leading Wildcard
Leading wildcard in LIKE prevents index usage. Move % to the end if possible.
SELECT * FROM users WHERE name LIKE '%Silva'SELECT id, name, email FROM users WHERE name LIKE 'Silva%'Window Function Best Practice
Consider if window function should use PARTITION BY to group calculations.
SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn, name FROM usersSELECT ROW_NUMBER() OVER (PARTITION BY cidade ORDER BY id) AS rn, name FROM users