Search Postgresql Archives

Re: DISTINCT *and* ORDER BY in aggregate functions on expressions(!)y

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> On 3 Mar 2023, at 20:32, Thorsten Glaser <tg@xxxxxxxxxxx> 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.










[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]

  Powered by Linux