DEV Community

Cover image for Mastering CTEs in SQL: A Beginner's Guide with Real-World Use Cases (PostgreSQL Edition).
Richa Parekh
Richa Parekh

Posted on

Mastering CTEs in SQL: A Beginner's Guide with Real-World Use Cases (PostgreSQL Edition).

SQL, or "Sequel" as some call it, seems super easy at first. You just type something like SELECT * FROM and suddenly you're looking at data from a database. Pretty cool, right? But SQL can do so much more than just simple stuff. There are powerful tricks hidden in there, and one of the best is called Common Table Expressions, or CTEs for short.

CTEs are a big deal. They can help you with all sorts of things, like making dashboards, running fancy reports, or even solving tricky problems that repeat themselves. In this article, I'm going to explain what CTEs are, how they work, when they're most useful, and show you some real-world use cases. We'll be using PostgreSQL, which is a fantastic and free database system.

I'll also share with you a small project I made myself to explore advanced SQL concepts.

πŸ” What is a CTE?

A Common Table Expression (CTE) is a temporary result set that you can reference within a SELECT, INSERT, UPDATE, or DELETE statement. Think of it like a named subquery that enhances readability and maintainability.

πŸ”§ Basic Syntax

WITH cte_name AS (
    SELECT column1, column2
    FROM your_table
    WHERE condition
)
SELECT * FROM cte_name;
Enter fullscreen mode Exit fullscreen mode

PostgreSQL evaluates the CTE first, then uses the result in the main query.

πŸ’‘ Real-World Use Cases of CTEs

1. Simplifying Complex Joins & Filters

Nested subqueries can become unreadable. CTEs help you break them into manageable parts.

πŸ“Œ Example:

WITH recent_orders AS (
    SELECT * FROM orders WHERE order_date > CURRENT_DATE - INTERVAL '30 days'
),
high_value_orders AS (
    SELECT * FROM recent_orders WHERE total_amount > 500
)
SELECT customer_id, COUNT(*) 
FROM high_value_orders 
GROUP BY customer_id;
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Use case: A sales dashboard needs to show active high-value customers in the last 30 days.

2. Recursive Queries

CTEs support recursion β€” great for working with hierarchical or graph-like data (e.g., org charts, category trees).

πŸ“Œ Example: Finding management hierarchy

WITH RECURSIVE org_chart AS (
    SELECT id, name, manager_id FROM employees WHERE id = 1
    UNION ALL
    SELECT e.id, e.name, e.manager_id
    FROM employees e
    INNER JOIN org_chart oc ON e.manager_id = oc.id
)
SELECT * FROM org_chart;
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Use case: Performing a recursive query of all employees under a given manager.

3. Updating with Joins (a CTE hack)

CTEs allow you to "stage" complex data before it is updated or deleted.

πŸ“Œ Example:

WITH flagged_users AS (
    SELECT user_id FROM login_attempts
    GROUP BY user_id
    HAVING COUNT(*) > 10
)
UPDATE users
SET is_locked = TRUE
WHERE id IN (SELECT user_id FROM flagged_users);
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Use case: Lock accounts that exceed failed login limits.

πŸ“š Rules, Restrictions & Tips

βœ… Rules

  • CTEs are declared using WITH, followed by one or more comma-separated blocks.
  • You can use CTEs in SELECT, INSERT, UPDATE, and DELETE.
  • Recursive CTEs must be explicitly marked with WITH RECURSIVE.

⚠️ Restrictions & Performance Tips

  • PostgreSQL materializes CTEs by default. This means that the results of the CTE query are stored in a temporary structure, often in memory, and then used in the outer query.
    • β›” Why it matters: In performance-critical queries, this can cause slower execution than expected.
    • βœ… Fix: From PostgreSQL 12+, you can use MATERIALIZED or NOT MATERIALIZED to control this behavior. πŸ“Œ Example:
WITH cte_name AS NOT MATERIALIZED (
    SELECT * FROM large_table WHERE condition
)
SELECT * FROM cte_name;
Enter fullscreen mode Exit fullscreen mode
  • Use CTEs wisely. Sometimes replacing a CTE with an inline subquery improves speed.

πŸ” RDBMS Support

Feature PostgreSQL MySQL SQL Server Oracle
Basic CTE βœ… βœ… (v8.0+) βœ… βœ…
Recursive CTE βœ… βœ… (v8.0+) βœ… βœ…
Materialized CTE βœ… (v12+) ❌ ❌ ❌

βœ… PostgreSQL stands out for flexibility and control over CTE behavior.

πŸ–₯️ My SQL and PostgreSQL Learning Project

Title: Online Learning Platform (SQL-Only Backend)
For real-world knowledge with PostgreSQL, I created a backend system for an online learning platform that was totally written in SQL and had no frameworks, ORMs, or external tools.
The platform mimics real-world systems like Coursera or Udemy with practice like:

  1. Schema Design
  2. Query Practice
    • 10 Beginner-level queries
    • 10 Intermediate queries
    • Advanced queries using:
    • CTEs
    • Transactions
    • Window functions
    • Triggers and functions
  3. Access Control & Security
    • Role-based access
    • PostgreSQL roles & permissions
    • Row-Level Security (RLS) setup
  4. Views
    • Logical abstraction with views
    • Performance optimization with materialized views

πŸš€Explore more
πŸ”— GitHub Repository link: Online Learning Platform (SQL-Only Backend)

Conclusion

If you want to write clean, reusable, and powerful SQL queries, you must understand CTEs. They not only increase readability but also enable recursive logic and maintainable data transformations.

MATERIALIZED control gives you more power when working with PostgreSQL, making it ideal for performance changes.

CTEs are more than simply a "nice-to-have"β€”they are essential parts of complex SQL operations.

Share Your Thoughts

Have you ever used CTEs in your projects? What were the problems or benefits you experienced? Please let me know in the comments below!

Happy coding!✨

Google AI Education track image

Build Apps with Google AI Studio 🧱

This track will guide you through Google AI Studio's new "Build apps with Gemini" feature, where you can turn a simple text prompt into a fully functional, deployed web application in minutes.

Read more β†’

Top comments (0)

Google AI Education track image

Build Apps with Google AI Studio 🧱

This track will guide you through Google AI Studio's new "Build apps with Gemini" feature, where you can turn a simple text prompt into a fully functional, deployed web application in minutes.

Read more β†’

πŸ‘‹ Kindness is contagious

Discover fresh viewpoints in this insightful post, supported by our vibrant DEV Community. Every developer’s experience mattersβ€”add your thoughts and help us grow together.

A simple β€œthank you” can uplift the author and spark new discussionsβ€”leave yours below!

On DEV, knowledge-sharing connects us and drives innovation. Found this useful? A quick note of appreciation makes a real impact.

Okay