Đ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ớifloat8
để làm cho nó hoạt động, đó chỉ là một bí danh chodouble 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ụngnumeric
thay vào đó. - Vì bạn
GROUP BY last_name
bạn muốn mộttext
đơn giản Tham số OUT thay vìtext[]
.
- kết quả của
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