Trong Postgres 9.3 hoặc sau này điều này được giải quyết tốt nhất bằng LATERAL
tham gia:
SELECT *
FROM actors a
JOIN movies_actors ma on a.actor_id = ma.movie_id
LEFT JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
LIMIT 10;
Tránh đánh giá hàm lặp lại (đối với mỗi cột trong đầu ra - hàm phải được gọi cho mỗi hàng đầu vào theo cách nào đó).
LEFT JOIN LATERAL ... ON true
để tránh giảm hàng từ phía bên trái nếu hàm trả về không có hàng:
- Sự khác biệt giữa LATERAL và một truy vấn con trong PostgreSQL là gì?
Theo dõi trong bình luận của bạn:
chỉ các cột được mở rộng do lệnh gọi hàm tạo ra
SELECT x.* -- that's all!
FROM actors a
JOIN movies_actors ma on a.actor_id = ma.movie_id
LEFT JOIN LATERAL hi_lo(a.actor_id, length(a.name), ma.movie_id) x ON true
LIMIT 10;
Nhưng vì bạn không quan tâm đến các cột khác, bạn có thể đơn giản hóa thành:
SELECT x.*
FROM actors a
JOIN movies_actors ma on a.actor_id = ma.movie_id
, hi_lo(a.actor_id, length(a.name), ma.movie_id) x
LIMIT 10;
Đây là một CROSS JOIN LATERAL
ngầm định . Nếu đôi khi hàm thực sự có thể trả về "không có hàng", thì kết quả có thể khác:chúng tôi không nhận được giá trị NULL cho các hàng, các hàng đó chỉ bị loại bỏ - và LIMIT
không tính chúng nữa.
Trong phiên bản cũ hơn (hoặc nói chung) bạn cũng có thể chỉ cần phân tách kiểu kết hợp với cú pháp phù hợp:
SELECT *, (hi_lo(a.actor_id, length(a.name), ma.movie_id)).* -- note extra parentheses!
FROM actors a
JOIN movies_actors ma on a.actor_id = ma.movie_id
LIMIT 10;
Hạn chế là hàm được đánh giá một lần cho mỗi cột trong đầu ra hàm do một điểm yếu trong bộ lập kế hoạch truy vấn Postgres. Tốt hơn nên chuyển lệnh gọi vào truy vấn con hoặc CTE và phân tách loại hàng trong SELECT
bên ngoài . Như:
SELECT actor_id, movie_id, (x).* -- explicit column names for the rest
FROM (
SELECT *, hi_lo(a.actor_id, length(a.name), ma.movie_id) AS x
FROM actors a
JOIN movies_actors ma on a.actor_id = ma.movie_id
LIMIT 10
) sub;
Nhưng bạn phải đặt tên cho các cột riêng lẻ và không thể sử dụng SELECT *
trừ khi bạn đồng ý với loại hàng trong kết quả dư thừa.
- Tránh nhiều lệnh gọi trên cùng một hàm khi mở rộng kết quả tổng hợp
- Làm cách nào để tránh nhiều lần trốn tránh hàm với cú pháp (func ()). * trong truy vấn SQL?