我正在尝试构造一个 Postgres 函数,它可以使用 where 子句中另一个 select 的结果。以下效果很好
create or replace function get_film_count(a varchar[], v varchar[])
RETURNS Table(costs decimal, id varchar, in_node varchar[], out_node varchar[], cycle BOOLEAN,visted_list varchar[])
language plpgsql
as
'
begin
RETURN QUERY SELECT edg.costs, edg.id, ARRAY[edg.in_node], ARRAY[edg.out_node], edg.in_node = ANY(v), v || ARRAY[edg.in_node]
FROM edges edg where edg.in_node=ANY(a) AND edg.in_node != ANY(v)
union all
SELECT edg.costs, edg.id, ARRAY[edg.in_node], ARRAY[edg.out_node], edg.in_node = ANY(v), v || ARRAY[edg.in_node]
FROM edges edg where edg.in_node=ANY(SELECT edg.out_node
FROM edges edg where edg.in_node=ANY(a) AND edg.in_node != ANY(v));
end;
';
select * from get_film_count(ARRAY['a'], ARRAY['']);
但是我正在寻找类似于以下内容的东西
create or replace function get_film_count(a varchar[], v varchar[])
RETURNS Table(costs decimal, id varchar, in_node varchar[], out_node varchar[], cycle BOOLEAN,visted_list varchar[])
language plpgsql
as
'
begin
list_of_out_nodes= select out_node from (get_film_count(ARRAY(edg.out_node), v || ARRAY[edg.in_node]))
RETURN QUERY SELECT edg.costs, edg.id, ARRAY[edg.in_node], ARRAY[edg.out_node], edg.in_node = ANY(v), v || ARRAY[edg.in_node]
FROM edges edg where edg.in_node=ANY(a) AND edg.in_node != ANY(v)
union all
SELECT edg.costs, edg.id, ARRAY[edg.in_node], ARRAY[edg.out_node], edg.in_node = ANY(v), v || ARRAY[edg.in_node]
FROM edges edg where edg.in_node=ANY(list_of_out_nodes);
end;
';
select * from get_film_count(ARRAY['a'], ARRAY['']);
所以基本上我正在寻找使用递归调用函数来代替并获取列的值作为列表并将其输入返回查询中 注意:我知道 Postgres 的递归功能,但我专门寻找这种方法
我相信您将需要一个 CTE 来允许第一个函数调用返回的集合在第二个调用中可用,如下所示:
CREATE OR REPLACE FUNCTION get_film_count(a varchar[], v varchar[])
RETURNS TABLE(costs decimal, id varchar, in_node varchar[], out_node varchar[], cycle BOOLEAN, visited_list varchar[])
LANGUAGE plpgsql
AS $$
DECLARE
list_of_out_nodes varchar[];
BEGIN
RETURN QUERY
WITH recursive_nodes AS (
SELECT edg.out_node
FROM get_film_count(ARRAY[edg.out_node], v || ARRAY[edg.in_node])
)
SELECT edg.costs, edg.id, ARRAY[edg.in_node], ARRAY[edg.out_node], edg.in_node = ANY(v), v || ARRAY[edg.in_node]
FROM edges edg
WHERE edg.in_node = ANY(a) AND edg.in_node != ANY(v)
UNION ALL
SELECT edg.costs, edg.id, ARRAY[edg.in_node], ARRAY[edg.out_node], edg.in_node = ANY(v), v || ARRAY[edg.in_node]
FROM edges edg
WHERE edg.in_node = ANY((SELECT * FROM recursive_nodes));
END; $$;
不过,我不能说我对这个概念非常热衷。看起来过于“聪明”,可能是一个支持问题(这只是直觉!)。