Những gì bạn đang cố gắng có thể hoạt động như thế này:
Chỉnh sửa với thông tin bổ sung
CREATE OR REPLACE FUNCTION f_products_per_month()
RETURNS SETOF fcholder AS
$BODY$
DECLARE
r fcholder;
BEGIN
FOR r.y, r.m IN
SELECT to_char(x, 'YYYY')::int4 -- AS y
,to_char(x, 'MM')::int4 -- AS m
FROM (SELECT '2008-01-01 0:0'::timestamp
+ (interval '1 month' * generate_series(0,57)) AS x) x
LOOP
RETURN QUERY
SELECT * -- use '*' in this case to stay in sync
FROM get_forecast_history(r.m, r.y);
IF NOT FOUND THEN
RETURN NEXT r;
END IF;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql;
Gọi:
SELECT * FROM f_products_per_month();
Những điểm chính:
- Chỉnh sửa lần cuối để bao gồm một hàng trống trong nhiều tháng không có sản phẩm.
- Bạn đã viết "LEFT JOIN", nhưng đó không phải là cách nó có thể hoạt động.
- Có một số cách để thực hiện việc này, nhưng
RETURN QUERY
là thanh lịch nhất. - Sử dụng cùng kiểu trả về như hàm get_forecast_history () của bạn sử dụng.
- Tránh đặt tên xung đột với các thông số OUT bằng cách phân loại tên cột trong bảng (không áp dụng được nữa trong phiên bản cuối cùng).
- Không sử dụng
DATE '2008-01-01'
, hãy sử dụng dấu thời gian như tôi đã làm, dù sao thì nó cũng phải được chuyển đổi thành to_char (). Truyền ít hơn, hoạt động tốt hơn (không phải là vấn đề quan trọng trong trường hợp này). -
'2008-01-01 0:0'::timestamp
vàtimestamp '2008-01-01 0:0'
chỉ là hai biến thể cú pháp hoạt động giống nhau. - Đối với các phiên bản cũ hơn của PostgreSQL, ngôn ngữ plpgsql không được cài đặt bởi defualt. Bạn có thể phải phát hành
CREATE LANGUAGE plpgsql;
một lần trong cơ sở dữ liệu của bạn. Xem hướng dẫn tại đây .
Bạn có thể đơn giản hóa hai hàm của mình thành một truy vấn hoặc hàm nếu bạn muốn.