Re: DISTINCT *and* ORDER BY in aggregate functions on expressions(!)y - Mailing list pgsql-general

From Alban Hertroys
Subject Re: DISTINCT *and* ORDER BY in aggregate functions on expressions(!)y
Date
Msg-id 82E2D483-67A9-480D-8671-8937D077840B@gmail.com
Whole thread Raw
In response to Re: DISTINCT *and* ORDER BY in aggregate functions on expressions(!)y  (Thorsten Glaser <tg@evolvis.org>)
Responses Re: DISTINCT *and* ORDER BY in aggregate functions on expressions(!)y  (Thorsten Glaser <tg@evolvis.org>)
List pgsql-general
> On 3 Mar 2023, at 20:32, Thorsten Glaser <tg@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
thefunction result. 
I used a cross join because there is no join condition to apply to the lateral, otherwise you could also use an inner
joinon true. 

I think you could also have used an implicit Cartesian product (using ‘,’ for the join), and that in that case the
lateralwould 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
markedas 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
sidegets executed first, after which the results of the other side of the join get merged to this, or whether this can
allbe 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
objectmembers, such as in your case. 

Regards,

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







pgsql-general by date:

Previous
From: Ron
Date:
Subject: Re: Dropping behavior for unique CONSTRAINTs
Next
From: "Peter J. Holzer"
Date:
Subject: Re: Dropping behavior for unique CONSTRAINTs