> On 3 Mar 2023, at 20:32, Thorsten Glaser <t...@evolvis.org> wrote:
> 
> On Fri, 3 Mar 2023, Alban Hertroys wrote:
> 
>> You can rewrite that into something like this:
>> 
>> select jsonb_build_object('opening_times’,
>>      obj
>>      ORDER BY
>>          obj->>'weekday’,
>>          obj->>'from_hour’,
>>          obj->>'to_hour')
>> )
>> from cot
>> cross join lateral jsonb_agg(jsonb_build_object(
>>              'weekday', cot.weekday,
>>              'from_hour', cot.from_hour,
>>              'to_hour', cot.to_hour) obj
> 
> But isn’t that the same as with a regular LEFT JOIN?

Similar, but not the same, I’d say.

I do now notice that I made some copying errors there, I was a bit nauseous at 
that time.
That should have read:

>> select jsonb_build_object('opening_times’,
>>     jsonb_agg(obj
>>      ORDER BY
>>          obj->>'weekday’,
>>          obj->>'from_hour’,
>>          obj->>'to_hour')
>> )
>> from cot
>> cross join lateral jsonb_build_object(
>>              'weekday', cot.weekday,
>>              'from_hour', cot.from_hour,
>>              'to_hour', cot.to_hour) obj


The lateral join applies the function to each row returned from the left side 
of the join and enriches that row with the function result.
I used a cross join because there is no join condition to apply to the lateral, 
otherwise you could also use an inner join on true.

I think you could also have used an implicit Cartesian product (using ‘,’ for 
the join), and that in that case the lateral would be implied. I prefer 
explicit notation though.

A left join wouldn’t make much sense here, unless the function could return 
NULL - for example if it were a function marked as STRICT and some of the input 
parameter values (from the table) could be NULL.


>>>   cgwaj AS (
>>>     SELECT cgwa.id AS id, jsonb_build_object(
>>>             'weekday', cgwa.weekday,
>>>             'forenoon', cgwa.forenoon,
>>>             'afternoon', cgwa.afternoon,
>>>             'evening', cgwa.evening) AS obj
>>>     FROM core_generalworkavailability cgwa
> 
> plus

There are some differences.

You need a sub-select, which in turn creates its own result set. It’s up to the 
planner whether the left or the right side gets executed first, after which the 
results of the other side of the join get merged to this, or whether this can 
all be collected in one go. That’s up to the query planner to decide though, 
and it could be right.

>>>     LEFT JOIN cgwaj ON cgwaj.id=cppwt.generalworkavailability_id
> 
> With the addition that I can aggregate…

You can do so in both situations, but I guess that confusion stems from my 
copy/paste mistake.

In my experience, lateral joins go well with the jsonb functions. They tend to 
reduce code repetition when referencing object members, such as in your case.

Regards,

Alban Hertroys
--
There is always an exception to always.






Reply via email to