> On 3 Mar 2023, at 20:32, Thorsten Glaser <[email protected]> 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.