Working with Common Table Expressions (CTEs) in PostgreSQL

Introduction

Common Table Expressions (CTEs) in PostgreSQL provide a way to write complex queries in a more readable and maintainable manner. CTEs allow you to define temporary result sets that can be referenced within the main query, making SQL statements more structured and easier to understand.

This article explores:

  • The basics of CTEs
  • Using recursive and non-recursive CTEs
  • Practical examples with the Reservations table

Understanding CTEs in PostgreSQL

A Common Table Expression (CTE) is defined using the WITH keyword, followed by a named query. The result of this query can then be used in subsequent queries.

Syntax:

WITH cte_name AS (
    SELECT column1, column2 FROM table_name WHERE condition
)
SELECT * FROM cte_name;

Using Non-Recursive CTEs

A non-recursive CTE is simply a named subquery that makes queries more readable.

Example:

WITH ConfirmedReservations AS (
    SELECT reservation_id, customer_id, total_rental_price
    FROM Reservations
    WHERE status = 'Confirmed'
)
SELECT * FROM ConfirmedReservations;

This query creates a temporary table of confirmed reservations and retrieves all its records, the output will be shown below :

carrentaldb=# WITH ConfirmedReservations AS (
SELECT reservation_id, customer_id, total_rental_price
FROM Reservations
WHERE status = 'Confirmed'
)
SELECT * FROM ConfirmedReservations;
reservation_id | customer_id | total_rental_price
----------------+-------------+--------------------
1 | 1 | 180.00
5 | 5 | 200.00
8 | 8 | 240.00
(3 rows)

Using Recursive CTEs

Recursive CTEs are useful for hierarchical data processing, such as organization structures or parent-child relationships.

Syntax:

WITH RECURSIVE cte_name AS (
    SELECT column1, column2 FROM table_name WHERE base_condition
    UNION ALL
    SELECT column1, column2 FROM table_name JOIN cte_name ON join_condition
)
SELECT * FROM cte_name;

Example:

WITH RECURSIVE ReservationChain AS (
    SELECT reservation_id, customer_id, pickup_date, return_date
    FROM Reservations
    WHERE reservation_id = 1  -- Base case
    UNION ALL
    SELECT r.reservation_id, r.customer_id, r.pickup_date, r.return_date
    FROM Reservations r
    JOIN ReservationChain rc ON r.customer_id = rc.customer_id
)
SELECT * FROM ReservationChain;

This query finds all reservations made by the same customer, starting from a given reservation.

Benefits of Using CTEs

  • Improves query readability and organization
  • Avoids redundant subqueries
  • Enhances maintainability of complex queries
  • Enables hierarchical and recursive queries

Conclusion

Common Table Expressions (CTEs) in PostgreSQL provide a powerful way to simplify complex queries, making them more readable and maintainable. By using non-recursive and recursive CTEs, you can enhance data processing efficiency and handle hierarchical relationships effectively. Mastering CTEs will significantly improve your PostgreSQL query-writing skills.

You may also like