Working with LEFT JOIN: Mastering Outer Joins in PostgreSQL
Master the LEFT JOIN in PostgreSQL. Learn to retrieve all records from a primary table even when matching rows in related tables are missing.

Previously in this course, we explored Understanding INNER JOIN: Mastering Relational Queries in PostgreSQL to link tables that share matching values. While INNER JOIN is excellent for finding records with perfect pairs, it hides "orphan" records—data that exists in one table but lacks a counterpart in another.
In this lesson, we add the LEFT JOIN to your toolkit, allowing you to perform broader data retrieval by including all rows from your "left" (primary) table, regardless of whether a match exists in the "right" table.
Understanding LEFT JOIN from First Principles
In a relational database, a LEFT JOIN (a type of Outer Join) tells PostgreSQL: "Give me every row from the table on the left, and if you find a match in the table on the right, include that too."
If no match is found for a row on the left, PostgreSQL doesn't discard that row. Instead, it fills the columns from the right-hand table with NULL values. This is essential for reporting. For example, if you want a list of all customers, including those who have never placed an order, an INNER JOIN would silently exclude the inactive customers. A LEFT JOIN includes them, making the missing order data explicit as NULL.
LEFT JOIN vs INNER JOIN: A Quick Comparison
| Feature | INNER JOIN | LEFT JOIN |
|---|---|---|
| Matching rows | Included | Included |
| Unmatched left rows | Discarded | Included (with NULLs) |
| Unmatched right rows | Discarded | Discarded |
| Use Case | Strict relationships | Reporting all primary entities |
Worked Example: Finding Inactive Customers

Let’s apply this to our store project. We have a customers table and an orders table. We want to see a list of every customer and their order ID, even if they haven't bought anything yet.
SQLSELECT customers.name, orders.id AS order_id FROM customers LEFT JOIN orders ON customers.id = orders.customer_id;
When you execute this, if customer_id 5 has no orders, the result will look like this:
| name | order_id |
|---|---|
| Alice | 101 |
| Bob | NULL |
| Charlie | 102 |
The NULL in the order_id column is the database's way of signaling that there is no related record in the orders table for Bob.
Hands-on Exercise: Identifying Products without Sales
Building on our store schema, practice your data retrieval skills by identifying which products haven't sold yet.
- Write a query using
LEFT JOINbetween theproductstable and theorder_itemstable. - Select the product
nameand theorder_id(oridfromorder_items). - Observe how products with zero sales appear in your results with
NULLvalues.
Common Pitfalls
- Filtering out your own results: A common mistake is using a
WHEREclause that filters the right-side table (e.g.,WHERE orders.id > 100). If you filter on the right-side column, you effectively turn yourLEFT JOINback into anINNER JOINbecause theNULLvalues created by the join fail the filter test. Always check yourWHEREcriteria if you notice records disappearing. - Assuming every join is an INNER JOIN: Never assume that the result set will contain as many rows as the right-side table. If you join a
customerstable to anorderstable, you might end up with more rows than there are customers if one customer has multiple orders. - Confusing LEFT and RIGHT: While
RIGHT JOINexists, it is rarely used in professional environments. It is almost always cleaner to keep your primary table on the left and useLEFT JOINto maintain consistent, readable code.
FAQ
Why does my LEFT JOIN return more rows than I expected?
If a customer has placed three separate orders, the LEFT JOIN will create three rows for that customer (one for each order). If you only want to see the customer once, you would need to use aggregation, which we will cover in the next few lessons.
Is it possible to have multiple NULLs in the result?
Yes. If you join multiple tables (e.g., Customers -> Orders -> Shipments), and a customer has no orders, the columns for both orders and shipments will be NULL.
What is the difference between LEFT JOIN and LEFT OUTER JOIN?
None. In PostgreSQL, LEFT JOIN is shorthand for LEFT OUTER JOIN. They are functionally identical.
Recap
The LEFT JOIN is your primary tool for retrieving "everything from table A, plus what exists in table B." It prevents data loss by using NULL placeholders when relationships aren't met, which is invaluable for identifying gaps in your data. By understanding how these joins interact with WHERE clauses, you ensure your queries remain accurate and performant.
Up next: We will begin our exploration of Aggregate Functions, where we'll learn how to calculate totals and averages across your store's data.
Work with me

Laravel SaaS MVP & Multi-Tenant App Development
Launch your SaaS MVP on Laravel — multi-tenant, subscription-ready, and built by the engineer behind a platform serving 10,000+ paying users.

AI Automation & Agentic Workflow Development
Automate the repetitive work eating your time — content pipelines, data workflows, and agentic AI tasks that run themselves.


