I have a plpgsql function declared like this :
CREATE OR REPLACE FUNCTION dynamiccondition_byid(idcond INTEGER, OtherFilters TEXT)
RETURNS TABLE (id INTEGER, weight INTEGER)
I can get the individual values like this :
SELECT * FROM dynamiccondition_byid(1,'');
Now I have a table with several conditions and I want to get all the values for all conditions.
SELECT iddyncondition,dynamiccondition_byid(iddyncondition,'')
FROM dynconditions
Now I'm getting two columns : one with the iddyncondition and one with the result of the function in which the 2 values are combined with parens :
iddyncondition dynamiccondition_byid
-------------- ---------------------
1 (1234,5)
2 (5678,10)
I want to use the individual values (these are not arrays, I don't know what they are really).
The only way I have found is the following but I'm pretty sure the function is called twice for each line and performance is an issue :
SELECT iddyncondition
,(dynamiccondition_byid(iddyncondition,'')).id
,(dynamiccondition_byid(iddyncondition,'')).weight
FROM dynconditions
I would like to retrieve the data in a CTE like this (I'm using an array syntax so you get the idea but I know it is wrong) :
WITH dc AS (
SELECT iddyncondition,dynamiccondition_byid(iddyncondition,'') AS dcrec
FROM dynconditions
)
SELECT r.amountpaid,dc.weight
FROM rights r
JOIN royaltiesad ra USING(idoeu)
JOIN dc ON dc.iddyncondition=ra.iddyncondition and dc.dcrec[0]=r.idright;
Best Answer
You are right, the function will be called for each column if it used in the
select
clause even if it declared asimmutable
. The simple example:There are several notes:
If your function is not SRF, you could to declare it as
returns record
and useout
parameters to give the names to the returning fields;I used shorthand to retrieve all fields from the function.
The right way is to use
cross join
:Or for your case:
Update: following to the comment instead of
cross join lateral
you also can use:t cross join foo(t.x)
,t, lateral foo(t.x)
or justt, foo(t.x)
- all will works in same way. But I recommend to use at leastcross join
form for that case if some other tables will be involved in the query which makes it more clear.