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

Trả về các hàng phù hợp với các phần tử của mảng đầu vào trong hàm plpgsql

Điều này hoạt động:

CREATE OR REPLACE FUNCTION avg_purchases(last_names text[] = '{}')
  RETURNS TABLE(last_name text, avg_purchase_size float8) AS
$func$
   SELECT last_name, AVG(purchase_size)::float8
   FROM   purchases
   WHERE  last_name = ANY($1)
   GROUP  BY last_name
$func$  LANGUAGE sql;

Gọi:

SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');

Hoặc (cập nhật - ví dụ với báo giá đô la):

SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
  • Tìm hiểu thêm về cách trích dẫn các ký tự chuỗi:
    Chèn văn bản bằng các dấu ngoặc kép trong PostgreSQL

  • Bạn không cần SQL động ở đây.

  • Trong khi bạn có thể bọc nó thành một hàm plpgsql (có thể hữu ích), một hàm SQL đơn giản đang hoạt động tốt.

  • Bạn có loại không khớp .

    • kết quả của avg() có thể là numeric để giữ một kết quả chính xác. Tôi truyền tới float8 để làm cho nó hoạt động, đó chỉ là một bí danh cho double precision (bạn có thể sử dụng một trong hai). Nếu bạn cần độ chính xác hoàn hảo, hãy sử dụng numeric thay vào đó.
    • Vì bạn GROUP BY last_name bạn muốn một text đơn giản Tham số OUT thay vì text[] .

VARIADIC

Mảng là một kiểu đầu vào hữu ích. Nếu nó dễ dàng hơn cho khách hàng của bạn, bạn cũng có thể sử dụng VARIADIC tham số đầu vào cho phép truyền mảng dưới dạng danh sách các phần tử :

CREATE OR REPLACE FUNCTION avg_purchases(VARIADIC last_names text[] = '{}')
  RETURNS TABLE(last_name text, avg_purchase_size float8) AS
$func$
   SELECT last_name, AVG(purchase_size)::float8
   FROM   purchases
   JOIN  (SELECT unnest($1)) t(last_name) USING (last_name)
   GROUP  BY last_name
$func$  LANGUAGE sql;

Gọi:

SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');

Hoặc (với báo giá đô la):

SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);

Lưu ý rằng Postgres tiêu chuẩn chỉ cho phép tối đa 100 phần tử . Điều này được xác định tại thời điểm biên dịch bởi tùy chọn đặt trước:

max_function_args (integer)

Báo cáo số lượng tối đa các đối số của hàm. Nó được xác định bởi giá trị của FUNC_MAX_ARGS khi xây dựng máy chủ. Giá trị mặc định là 100 đối số.

Bạn vẫn có thể gọi nó bằng ký hiệu mảng khi được đặt trước bằng từ khóa VARIADIC :

SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');

Đối với các mảng lớn hơn (100+), tôi cũng sẽ sử dụng unnest() trong một truy vấn con và JOIN đối với nó, có xu hướng mở rộng quy mô tốt hơn:

  • Tối ưu hóa truy vấn Postgres với IN lớn



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chèn nhiều hàng với pg-promise

  2. 2ndQuadrant Deutschland - Mặc cả khai mạc khóa huấn luyện đặc biệt

  3. Tạo chuỗi thời gian giữa hai ngày trong PostgreSQL

  4. Timezone_types khác nhau trên đối tượng DateTime

  5. Chuyển nhiều giá trị trong một tham số duy nhất