22nd Apr 2025 4 minutes read The Most Useless SQL Queries (and What you Should do Instead) LearnSQL.com Team sql practice SQL Table of Contents 1. Selecting Everything Without a Purpose 2. Counting Everything Without Filtering 3. Order By Default When Order Doesn’t Matter 4. Sorting Without a Limit 5. Grouping Without Meaningful Labels 6. Using HAVING Instead of WHERE for Filtering Rows 7. Filtering on Computed Columns Without Indexing 8. Using Subqueries Instead of Joins 9. Self-Joining Instead of Using Window Functions Write Smarter SQL, not Just Valid SQL They run. They return data. But they’re pointless. Here’s what not to write in SQL – and what to do instead. Some SQL queries run just fine – but that doesn’t mean they’re doing anything useful. In this article, we’ll walk through real examples of SQL queries that are valid, harmless-looking, and completely pointless. They waste resources, hide insights, or just add noise. For each one, you’ll see what’s wrong, and how to write a smarter alternative instead. Want to practice writing better queries right away? Try the SQL Practice track on LearnSQL.com – it’s built to help you turn theory into skill, with 12 courses and over 1000 interactive exercises. Let’s clean up the junk and write queries that actually get the job done. 1. Selecting Everything Without a Purpose The query: SELECT * FROM orders; Why it’s useless: pulls unnecessary data, slows down queries, and burdens the database. What to do instead: specify only the required columns to improve performance. Better query: SELECT order_id, customer_id, total_amount FROM orders; 2. Counting Everything Without Filtering The query: SELECT COUNT(*) FROM orders; Why it’s useless: often returns misleading insights if not filtered. What to do instead: use WHERE conditions or GROUP BY for better accuracy. Better query: SELECT COUNT(*) FROM orders WHERE status = 'completed'; 3. Order By Default When Order Doesn’t Matter The query: SELECT total_amount FROM orders ORDER BY customer_id; Why it’s useless: adds processing time without benefiting analysis. What to do instead: use ORDER BY intentionally, e.g., for reporting or visualization. Better query: do not use ORDER BY unless necessary; SELECT total_amount FROM orders; 4. Sorting Without a Limit This one is similar to the previous one. The query: SELECT order_id, customer_id, total_amount FROM orders ORDER BY created_at DESC; Why it’s useless: sorting large datasets without constraints is inefficient. What to do instead: if possible, use LIMIT or TOP. Better query: SELECT order_id, customer_id, total_amount FROM orders ORDER BY created_at DESC LIMIT 10; 5. Grouping Without Meaningful Labels The query: SELECT customer_id, COUNT(*) FROM orders GROUP BY customer_id; Why it’s useless: IDs alone don’t provide context – the results are hard to interpret and not actionable. What to do instead: make sure to include a meaningful label like name or email. Better query: SELECT o.customer_id, c.email, COUNT(*) AS total_orders FROM orders o JOIN customers c ON o.customer_id = c.id GROUP BY o.customer_id, c.email; 6. Using HAVING Instead of WHERE for Filtering Rows The query: SELECT order_id, customer_id, total_amount FROM orders HAVING total_amount > 100; Why it’s useless: HAVING is meant for aggregate filtering, not row filtering. While it technically works, it will distract the reader of the query from understanding your intention. What to do instead: use WHERE before aggregation. Better query: SELECT order_id, customer_id, total_amount FROM orders WHERE total_amount > 100; 7. Filtering on Computed Columns Without Indexing The query: SELECT order_id, customer_id, total_amount FROM orders WHERE YEAR(created_at) = 2023; Why it’s useless: prevents index usage, causing full table scans. What to do instead: use range-based filtering to leverage indexes. Better query: SELECT order_id, customer_id, total_amount FROM orders WHERE created_at >= '2023-01-01' AND created_at < '2024-01-01'; 8. Using Subqueries Instead of Joins The query: SELECT order_id, customer_id, total_amount FROM orders WHERE customer_id IN (SELECT customer_id FROM blacklisted_customers); Why it’s useless: can lead to slow performance compared to JOINs. What to do instead: use an INNER JOIN or LEFT JOIN. Better query: SELECT o.order_id, o.customer_id, o.total_amount FROM orders o JOIN blacklisted_customers b ON o.customer_id = b.customer_id; 9. Self-Joining Instead of Using Window Functions The query: SELECT o1.customer_id, o1.order_id, COUNT(*) AS row_num FROM orders o1 JOIN orders o2 ON o1.customer_id = o2.customer_id AND o1.order_date >= o2.order_date GROUP BY o1.customer_id, o1.order_id; Why it’s useless: causes unnecessary complexity and duplication. What to do instead: use window functions like ROW_NUMBER(), RANK(), or LAG(). Better query: SELECT customer_id, order_id, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) AS row_num FROM orders; Write Smarter SQL, not Just Valid SQL Just because a query runs doesn’t mean it’s helping. Avoiding these common traps will make your SQL faster, cleaner, and way more useful. If you want to keep practicing the right way to write queries, check out the SQL Practice track on LearnSQL.com. It’s packed with hands-on exercises that help you sharpen your skills by doing – not just reading. Tags: sql practice SQL