Skip to content
>GLB_
Go back

How Joins Work in PostgreSQL

Joins are one of the most powerful features in SQL, allowing you to combine data from multiple tables in a single query. PostgreSQL, as a relational database system, provides robust support for different types of joins. Understanding how joins work under the hood helps you write more efficient queries and troubleshoot performance issues.


What Is a Join?

A join combines rows from two or more tables based on a related column between them. This is commonly used to retrieve meaningful data that is stored in normalized structures.

Example:

SELECT o.order_id, c.customer_name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;

This retrieves a list of orders along with the corresponding customer name.


Types of Joins in PostgreSQL

1. Inner Join

Returns rows when there is a match in both tables.

SELECT * FROM orders o
INNER JOIN customers c ON o.customer_id = c.customer_id;

2. Left Join (Left Outer Join)

Returns all rows from the left table, and the matched rows from the right table. NULLs are returned if there’s no match.

SELECT * FROM orders o
LEFT JOIN customers c ON o.customer_id = c.customer_id;

3. Right Join (Right Outer Join)

Returns all rows from the right table, and the matched rows from the left table.

SELECT * FROM orders o
RIGHT JOIN customers c ON o.customer_id = c.customer_id;

4. Full Outer Join

Returns rows when there is a match in either left or right table.

SELECT * FROM orders o
FULL OUTER JOIN customers c ON o.customer_id = c.customer_id;

5. Cross Join

Returns the Cartesian product of both tables.

SELECT * FROM orders o
CROSS JOIN customers c;

How PostgreSQL Executes Joins

PostgreSQL uses different algorithms to execute joins depending on data size, indexing, and query structure:

1. Nested Loop Join

2. Hash Join

3. Merge Join

You can inspect how a join is executed using:

EXPLAIN SELECT ... FROM ... JOIN ...;

Or with execution stats:

EXPLAIN ANALYZE SELECT ...;

Example EXPLAIN Output

EXPLAIN ANALYZE
SELECT o.order_id, c.customer_name
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id;

Might return:

Nested Loop  (cost=0.56..10.75 rows=5 width=64)
  ->  Index Scan using idx_orders_customer_id on orders o
  ->  Index Scan using idx_customers_id on customers c

This shows PostgreSQL using a Nested Loop with Index Scans.


Best Practices


Conclusion

Joins are critical for working with relational data. PostgreSQL offers a range of join types and optimizes execution based on the query context. Understanding how joins work — and how PostgreSQL chooses execution plans — helps you write faster, more reliable queries.

What’s your favorite join type or optimization trick? Drop a comment below!


Share this post:

Previous Post
Understanding .master() in Apache Spark
Next Post
How to Improve Query Performance in PostgreSQL