PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Chia bản ghi do hàm trả về thành nhiều cột

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?



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để định cấu hình HikariCP cho postgresql?

  2. Không thể kết nối với postgres từ máy chủ từ xa

  3. Tạo ràng buộc duy nhất với cột rỗng

  4. Sự cố với lệnh postgresql COPY với Rails trên máy chủ khác nhau

  5. ClusterControl - Quản lý sao lưu nâng cao - PostgreSQL