Mastering SQL: Optimizing Queries with Smarter Techniques

Table of contents
- 1️⃣ COALESCE vs. ISNULL – Handling NULLs the Right Way
- 2️⃣ Avoid IN – Use JOIN for Better Performance
- 3️⃣ Aliases – A Good Practice Even for Simple Queries
- 4️⃣ GROUP BY vs. PARTITION BY – Understanding the Difference
- 5️⃣ LAG & LEAD – Accessing Previous & Next Row Data
- 6️⃣ RANK() vs. DENSE_RANK() – Choosing the Right Ranking
- 7️⃣ JOIN vs. UNION – How They Differ
- 8️⃣ The Power of SUBSTRING() , STRING_AGG() , GROUP_CONCAT()
- 9️⃣ The Benefit of CTEs & Aliasing Subqueries
- 🔟 Optimizing JOIN Conditions – AND vs. WHERE
- 1️⃣1️⃣ Avoid SELECT * – Specify Columns
- 1️⃣2️⃣ SQL Execution Order –
- 1️⃣3️⃣ Using LEFT() & RIGHT() for String Manipulation
- Final Thoughts

SQL is powerful, but writing efficient and readable queries makes all the difference. While working on various databases, I’ve discovered some underrated SQL concepts that improve both performance and maintainability.
Let’s explore some key SQL best practices, with practical examples to help you optimize your queries!
1️⃣ COALESCE
vs. ISNULL
– Handling NULLs the Right Way
Both COALESCE
and ISNULL
handle NULL values, but COALESCE offers more flexibility.
SELECT ISNULL(NULL, 'Fallback'); -- Returns: 'Fallback'
SELECT COALESCE(NULL, NULL, 'Fallback', 'Another Value'); -- Returns: 'Fallback'
✔ Use COALESCE when checking multiple values, as it returns the first non-null value.
✔ ISNULL is limited to two arguments and may cause unexpected type conversions.
2️⃣ Avoid IN
– Use JOIN
for Better Performance
Using IN
in subqueries is often slower than a JOIN
.
-- Using IN (Slower)
SELECT name FROM Employees WHERE department_id IN (SELECT id FROM Departments WHERE location = 'NY');
-- Using JOIN (Faster)
SELECT e.name FROM Employees e JOIN Departments d ON e.department_id = d.id WHERE d.location = 'NY';
✔ JOIN is optimized by the SQL engine and executes faster on large datasets.
3️⃣ Aliases – A Good Practice Even for Simple Queries
Aliases (AS
) improve readability and make queries more maintainable.
SELECT e.name AS EmployeeName, d.name AS DepartmentName
FROM Employees e
JOIN Departments d ON e.department_id = d.id;
✔ Even in small queries, aliasing enhances clarity and is extremely helpful in complex queries.
4️⃣ GROUP BY
vs. PARTITION BY
– Understanding the Difference
GROUP BY
aggregates data into a single row per group, whereas PARTITION BY
preserves all rows and applies window functions.
-- GROUP BY (Collapses rows)
SELECT department_id, COUNT(*) AS EmployeeCount FROM Employees GROUP BY department_id;
-- PARTITION BY (Keeps all rows)
SELECT name, department_id, COUNT(*) OVER (PARTITION BY department_id) AS EmployeeCount FROM Employees;
✔ Use GROUP BY for summary data.
✔ Use PARTITION BY when you need group-based calculations without losing row-level details.
5️⃣ LAG & LEAD – Accessing Previous & Next Row Data
When comparing current vs. previous/future records, LAG
& LEAD
eliminate the need for self-joins.
SELECT name, salary,
LAG(salary) OVER (ORDER BY id) AS PreviousSalary,
LEAD(salary) OVER (ORDER BY id) AS NextSalary
FROM Employees;
✔ LAG() fetches the previous row’s value.
✔ LEAD() fetches the next row’s value.
Ideal for trend analysis, financial reports, and comparative analytics.
6️⃣ RANK()
vs. DENSE_RANK()
– Choosing the Right Ranking
Both assign ranks, but they handle duplicates differently.
SELECT name, department, salary,
RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS Rank,
DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS DenseRank
FROM Employees;
✔ RANK()
skips numbers after duplicates. (eg. Rank - 1, 2, 2, 4, 5)
✔ DENSE_RANK()
assigns consecutive numbers. (eg. Rank - 1, 2, 2, 3, 4)
Use DENSE_RANK()
when you don’t want ranking gaps.
7️⃣ JOIN
vs. UNION
– How They Differ
JOIN
combines columns from multiple tables, while UNION
stacks rows.
-- JOIN (Merging column data)
SELECT e.name, d.name FROM Employees e JOIN Departments d ON e.department_id = d.id;
-- UNION (Stacking results)
SELECT name FROM Employees UNION SELECT name FROM Contractors;
✔ Use JOIN when you need more details from related tables.
✔ Use UNION when you want to combine results from similar tables.
8️⃣ The Power of SUBSTRING()
, STRING_AGG()
, GROUP_CONCAT()
SUBSTRING()
extracts parts of a string.Both
STRING_AGG
andGROUP_CONCAT
are used to concatenate multiple row values into a single string with a specified separator. However, there are some differences in syntax and capabilities.
SELECT SUBSTRING('Software Developer', 1, 8); -- Returns: 'Software'
SELECT
Class,
STRING_AGG(Name, ', ') WITHIN GROUP (ORDER BY Name ASC) AS StudentNames
FROM Students
GROUP BY Class;
SELECT
Class,
GROUP_CONCAT(Name ORDER BY Name ASC SEPARATOR ', ') AS StudentNames
FROM Students
GROUP BY Class;
✔ Great for data cleaning and reporting.
9️⃣ The Benefit of CTEs & Aliasing Subqueries
Common Table Expressions (CTEs) improve readability and avoid repeated subqueries.
WITH DepartmentCount AS (
SELECT department_id, COUNT(*) AS EmployeeCount FROM Employees GROUP BY department_id
)
SELECT e.name, d.EmployeeCount FROM Employees e JOIN DepartmentCount d ON e.department_id = d.department_id;
✔ CTEs enhance query structure and avoid nested complexity.
🔟 Optimizing JOIN
Conditions – AND vs. WHERE
Instead of filtering in WHERE
, apply conditions in ON
for better index usage.
-- Less efficient
SELECT e.name FROM Employees e JOIN Departments d ON e.department_id = d.id WHERE d.location = 'NY';
-- More efficient
SELECT e.name FROM Employees e JOIN Departments d ON e.department_id = d.id AND d.location = 'NY';
✔ ON
filters before the join happens, improving performance.
1️⃣1️⃣ Avoid SELECT *
– Specify Columns
Fetching only required columns improves query speed.
-- Avoid this
SELECT * FROM Employees;
-- Do this instead
SELECT name, salary FROM Employees;
✔ Reduces memory usage & speeds up query execution.
1️⃣2️⃣ SQL Execution Order –
Understanding execution order helps write optimized queries. The order is -
FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
SELECT department_id, COUNT(*)
FROM Employees
WHERE salary > 50000
GROUP BY department_id
HAVING COUNT(*) > 5;
✔ Queries execute in a different order than written. Hence, they should be written keeping in mind the execution order to improve performance. A useful mnemonic to remember SQL execution is:
"Fresh Juices With Great Healthy Sweet Orange Lemon"
Fresh → FROM
Juices → JOIN
With → WHERE
Great → GROUP BY
Healthy → HAVING
Sweet → SELECT
Orange → ORDER BY
Lemon → LIMIT
1️⃣3️⃣ Using LEFT()
& RIGHT()
for String Manipulation
SELECT LEFT('Developer', 3); -- Returns 'Dev'
SELECT RIGHT('Database', 4); -- Returns 'base'
✔ Great for handling text-based transformations.
Final Thoughts
Mastering these SQL techniques can significantly optimize queries, improve performance, and make your code cleaner and more maintainable. However, it’s important to note that SQL functions and behaviors can vary across different database engines.
For example:
GROUP_CONCAT
is available in MySQL but not in SQL Server or PostgreSQL. Instead, they useSTRING_AGG
.ISNULL
is specific to SQL Server, whereasCOALESCE
is ANSI SQL-compliant and works across PostgreSQL, MySQL, and others.LAG
andLEAD
are widely supported in modern databases but may have different implementations.
When working with SQL, always check the documentation of the specific database engine you’re using to ensure compatibility and take advantage of engine-specific optimizations.
👉 Which of these techniques have you used before? What other underrated SQL tricks have helped you? Let’s discuss!
Happy DevLogging! <3
#SQL #PerformanceTuning #DatabaseOptimization #BestPractices
Subscribe to my newsletter
Read articles from Samana Butool Mirza directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Samana Butool Mirza
Samana Butool Mirza
I am an aspiring developer with a creative flair for designing and a love for turning ideas into impactful solutions. From debugging code to crafting intuitive user experiences, I thrive on learning, growing, and sharing my journey in the ever-evolving tech world. When I’m not coding, you’ll find me exploring design tools, reading novels or...just sleeping.