Lesson 14 / 25

LATERAL Joins

A subquery per row.

Correlated subqueries in FROM

A LATERAL subquery can refer to columns of tables earlier in FROM, so it runs logically once per outer row. It is the cleanest way to get the top N related rows per row (each customer's latest two orders) and to call set-returning functions per row. Use CROSS JOIN LATERAL to drop rows with no results or LEFT JOIN LATERAL ... ON true to keep them. An index on (customer_id, ordered_on) makes it fast.

Each customer's two most recent orders, run

I ran this with psql on PostgreSQL 16.2 against the course sample data (shown in the first section). John has no orders and is dropped by CROSS JOIN LATERAL; the others show their latest two orders of any status.

-- Each customer's two most recent orders
SELECT c.name, recent.id, recent.ordered_on, recent.amount
FROM customers c
CROSS JOIN LATERAL (
  SELECT o.id, o.ordered_on, o.amount FROM orders o
  WHERE o.customer_id = c.id
  ORDER BY o.ordered_on DESC LIMIT 2
) AS recent
ORDER BY c.name, recent.ordered_on DESC;

Output:

 name  | id  | ordered_on | amount  
-------+-----+------------+---------
 Asha  | 106 | 2026-02-28 |  700.00
 Asha  | 102 | 2026-01-20 |  300.00
 Meera | 107 | 2026-03-01 |  150.00
 Meera | 105 | 2026-02-14 | 2000.00
 Ravi  | 104 | 2026-02-02 |  450.00
 Ravi  | 103 | 2026-01-21 |  800.00
(6 rows)

Compare with ROW_NUMBER

LATERAL with LIMIT can stop early per customer using an index, while ROW_NUMBER ranks all rows first.

Quick check: How do you keep outer rows with no LATERAL results?

  • Use UNION
  • CROSS JOIN LATERAL
  • Add DISTINCT
  • LEFT JOIN LATERAL (...) ON true
Answer

LEFT JOIN LATERAL (...) ON true — Like any left join.