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
|
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: