Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move set-returning function into a LATERAL FROM item PostgreSQL

I try this

select created_at, 
sum((json_array_elements(shipping_lines::json) ->> 'price')::float) as shipping_price
from t1
group by 1

It show Error:

ERROR: aggregate function calls cannot contain set-returning function calls LINE 5: sum(((json_array_elements(shipping_lines::json) ->> 'price')... ^ HINT: You might be able to move the set-returning function into a LATERAL FROM item.

How to fix this using Lateral From? I read this PsSQL docs but not really understand Lateral function

like image 828
Tom Tom Avatar asked Mar 27 '26 12:03

Tom Tom


2 Answers

That would be:

select t1.created_at, sum((x.obj->>'price')::float)  as shipping_price
from t1
left join lateral jsonb_array_element(t1.shipping_lines::jsonb) as x(obj) on true 
group by 1

Or, you can compute the sum() in the lateral join itself, which avoids the need for outer aggregation (assuming that created_at is unique in the table to start with):

select t1.created_at, x.shipping_price
from t1
cross join lateral (
    select sum((x.obj->>'price')::float) as shipping_price
    from jsonb_array_elements(t1.shipping_lines::jsonb) as x(obj)
) x

Note that I slightly changed the query to use jsonb instead of json: this new datatype is more flexible and efficient than json (even if it won't make a real difference here, it should be preferred whenever there is a choice).

like image 91
GMB Avatar answered Mar 30 '26 08:03

GMB


Hmmm. Move the logic to the from clause:

select created_at, sum( (j->>'price')::float) as shipping_price
from t1 left join lateral
     json_array_elements(shipping_lines::json) j
     on true
group by 1
like image 33
Gordon Linoff Avatar answered Mar 30 '26 09:03

Gordon Linoff



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!