Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive function in postgres

How to map below query to postgres function.

WITH RECURSIVE source (counter, product) AS (
SELECT
1, 1
UNION ALL
SELECT
counter + 1, product * (counter + 1)
FROM source
WHERE
counter < 10
)
SELECT counter, product FROM source;

I am new to postgres. I want to achieve same functionality using PL/pgsql function.

like image 918
PL-SQL Developer1000 Avatar asked May 06 '14 12:05

PL-SQL Developer1000


People also ask

How recursive query works in PostgreSQL?

PostgreSQL internally uses a working table to process recursive CTEs. This processing is not really recursive, but rather iterative: First, the working table is initialized by executing the non-recursive branch of the CTE. The result of the CTE is also initialized with this result set.

Can we use CTE in PostgreSQL?

In PostgreSQL, the CTE(Common Table Expression) is used as a temporary result set that the user can reference within another SQL statement like SELECT, INSERT, UPDATE or DELETE. CTEs are temporary in the sense that they only exist during the execution of the query.

What is recursive query example?

A recursive query is one that is defined by a Union All with an initialization fullselect that seeds the recursion. The iterative fullselect contains a direct reference to itself in the FROM clause.

How do I create a hierarchical query in PostgreSQL?

START WITH: Defines the records where we want the query to start. LEVEL: A pseudocolumn that indicates the level of hierarchy or row position. connect_by_root: Basically returns the rows using data from the root row. ORDER SIBLINGS BY: Applies the ORDER BY clause to the siblings rows.


1 Answers

A classic approach, known from other programming languages, in which a function calls itself:

create or replace function recursive_function (ct int, pr int)
returns table (counter int, product int)
language plpgsql
as $$
begin
    return query select ct, pr;
    if ct < 10 then
        return query select * from recursive_function(ct+ 1, pr * (ct+ 1));
    end if;
end $$;

select * from recursive_function (1, 1);

You can compare this with an iterative solution in a loop:

create or replace function loop_function ()
returns table (counter int, product int)
language plpgsql
as $$
declare
    ct int;
    pr int = 1;
begin
    for ct in 1..10 loop
        pr = ct* pr;
        return query select ct, pr;
    end loop;
end $$;

select * from loop_function ();

Of course, you can also put the recursive query inside an SQL function:

create or replace function recursive_query()
returns table (counter int, product int)
language sql
as $$
    with recursive source as (
        select 1 as counter, 1 as product
    union all
        select counter+ 1, product* (counter+ 1)
        from source
        where counter < 10
    )
    select counter, product
    from source
$$;

select * from recursive_query();
like image 110
klin Avatar answered Sep 28 '22 13:09

klin