LEFT JOIN LATERAL trong PostgreSQL hoạt động giống như một vòng lặp foreach trong SQL. Nó cho phép một truy vấn con (subquery) đọc và tham chiếu trực tiếp đến các cột của bảng đã được định nghĩa trước nó trong mệnh đề FROM.
Bình thường, các truy vấn con trong JOIN bị cô lập và không thể "nhìn thấy" dữ liệu của các bảng khác cùng cấp. Từ khóa LATERAL phá vỡ quy tắc này. Việc kết hợp với LEFT JOIN đảm bảo rằng nếu truy vấn con không tìm thấy kết quả nào, bản ghi ở bảng gốc (bên trái) vẫn được giữ lại (với các giá trị NULL).
Các trường hợp sử dụng phổ biến nhất
Truy vấn "Top N" cho mỗi nhóm (Top-N per group): Lấy 3 đơn hàng mới nhất của mỗi khách hàng, hoặc 5 bình luận mới nhất của mỗi bài viết. Cách dùng GROUP BY thông thường không làm được điều này.
Tính toán phức tạp từng dòng: Áp dụng một hàm tính toán hoặc hàm trả về nhiều tập hợp (set-returning function) dựa trên giá trị của từng dòng ở bảng bên trái.
Ví dụ : Lấy Top N đơn hàng của mỗi người dùng
Giả sử bạn có hai bảng: users (Người dùng) và orders (Đơn hàng). Bạn muốn hiển thị tất cả người dùng, kèm theo thông tin của tối đa 2 đơn hàng mới nhất của mỗi người.
Nếu dùng LEFT JOIN thông thường, bạn không thể giới hạn (LIMIT 2) cho riêng từng người dùng được. Với LEFT JOIN LATERAL, truy vấn sẽ như sau:
SELECT
u.id AS user_id,
u.name,
o.id AS order_id,
o.created_at,
o.total_amount
FROM
users u
LEFT JOIN LATERAL (
SELECT id, created_at, total_amount
FROM orders
WHERE user_id = u.id -- Tham chiếu trực tiếp u.id từ bảng users ở ngoài
ORDER BY created_at DESC
LIMIT 2 -- Chỉ lấy 2 đơn hàng mới nhất cho TỪNG user
) o ON true; -- Luôn dùng ON true vì điều kiện join đã nằm trong WHERE
Cách truy vấn này hoạt động:
PostgreSQL duyệt qua từng dòng trong bảng users.
Với mỗi người dùng, nó chạy truy vấn con bên trong khối LATERAL (truyền u.id vào điều kiện WHERE).
Truy vấn con sắp xếp các đơn hàng của riêng người dùng đó và cắt lấy đúng 2 đơn (LIMIT 2).
ON true được sử dụng vì logic kết nối bảng (user_id = u.id) đã được xử lý gọn gàng bên trong truy vấn con.
Vì là LEFT JOIN, những người dùng chưa từng mua hàng vẫn sẽ xuất hiện trong kết quả (với order_id và total_amount là NULL). Nếu bạn chỉ muốn hiện những người đã mua hàng, bạn sẽ dùng CROSS JOIN LATERAL (hoặc viết tắt là JOIN LATERAL).
LEFT JOIN LATERAL trong PostgreSQL hoạt động giống như một vòng lặp foreach trong SQL. Nó cho phép một truy vấn con (subquery) đọc và tham chiếu trực tiếp đến các cột của bảng đã được định nghĩa trước nó trong mệnh đề FROM.
Bình thường, các truy vấn con trong JOIN bị cô lập và không thể "nhìn thấy" dữ liệu của các bảng khác cùng cấp. Từ khóa LATERAL phá vỡ quy tắc này. Việc kết hợp với LEFT JOIN đảm bảo rằng nếu truy vấn con không tìm thấy kết quả nào, bản ghi ở bảng gốc (bên trái) vẫn được giữ lại (với các giá trị NULL).
Các trường hợp sử dụng phổ biến nhất
Truy vấn "Top N" cho mỗi nhóm (Top-N per group): Lấy 3 đơn hàng mới nhất của mỗi khách hàng, hoặc 5 bình luận mới nhất của mỗi bài viết. Cách dùng GROUP BY thông thường không làm được điều này.
Tính toán phức tạp từng dòng: Áp dụng một hàm tính toán hoặc hàm trả về nhiều tập hợp (set-returning function) dựa trên giá trị của từng dòng ở bảng bên trái.
Ví dụ : Lấy Top N đơn hàng của mỗi người dùng
Giả sử bạn có hai bảng: users (Người dùng) và orders (Đơn hàng). Bạn muốn hiển thị tất cả người dùng, kèm theo thông tin của tối đa 2 đơn hàng mới nhất của mỗi người.
Nếu dùng LEFT JOIN thông thường, bạn không thể giới hạn (LIMIT 2) cho riêng từng người dùng được. Với LEFT JOIN LATERAL, truy vấn sẽ như sau:
Cách truy vấn này hoạt động:
PostgreSQL duyệt qua từng dòng trong bảng users.
Với mỗi người dùng, nó chạy truy vấn con bên trong khối LATERAL (truyền u.id vào điều kiện WHERE).
Truy vấn con sắp xếp các đơn hàng của riêng người dùng đó và cắt lấy đúng 2 đơn (LIMIT 2).
ON true được sử dụng vì logic kết nối bảng (user_id = u.id) đã được xử lý gọn gàng bên trong truy vấn con.
Vì là LEFT JOIN, những người dùng chưa từng mua hàng vẫn sẽ xuất hiện trong kết quả (với order_id và total_amount là NULL). Nếu bạn chỉ muốn hiện những người đã mua hàng, bạn sẽ dùng CROSS JOIN LATERAL (hoặc viết tắt là JOIN LATERAL).