Postgre hàm LEFT JOIN LATERAL dùng làm gì ?

CU
cuongnv
Middle

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).

Cường không bd