[GENERAL] SQL question on chunking aggregates
Hi all: I have a table that has multiple records for a single owner_id. I'm able to use array_arg to combine the records into a single row, which works fine. I'm using this sql: select owner_id, array_agg(trim(maplot)), array_agg(revallandvalue + revalbuildingvalues) from parcel group by owner_id; Which results in the following (sometimes there's only one record per aggregate, sometimes multiple): 1030600;{154191};{244690} 1030900;{22202};{217210} 1031130;{113135,113138,113132,113130,113133,113 127,113126,113131,113129,113136,113125,113 137,113134,113 128};{7700,7700,7700,7700,7700,7700,7700,7700,7700,191770,7700,7700,7700,7700} What I want to do, is where there are more than 5 rows involved in the aggregate, as in the last example, to split it into multiple rows of 5 aggregated rows. It's for a mailing list and I want to combine like addresses into one record, but if I'm over 5, I have to print the rest on a separate letter. 1031130;{113135,113138,113132,113130,113 133};{7700,7700,7700,7700,7700} 1031130;{113127,113126,113131,113129,113 136};{7700, 7700,7700,7700,191770} 1031130;{113125,113137,113134,113 128};{7700,7700,7700,7700} It looks like I should be able to use the window function to do this, but I've been unsuccessful. The following runs, but doesn't seem to have any effect: select owner_id, array_agg(trim(maplot)), array_agg(revallandvalue + revalbuildingvalues) from parcel group by owner_id window mywindow as (rows between current row and 5 following); Does anyone have any suggestions on what I should try? -Owen
Re: [GENERAL] SQL question on chunking aggregates
On Tue, Mar 4, 2014 at 1:49 PM, Owen Hartnett o...@clipboardinc.com wrote: Hi all: I have a table that has multiple records for a single owner_id. I'm able to use array_arg to combine the records into a single row, which works fine. I'm using this sql: select owner_id, array_agg(trim(maplot)), array_agg(revallandvalue + revalbuildingvalues) from parcel group by owner_id; Which results in the following (sometimes there's only one record per aggregate, sometimes multiple): 1030600;{154191};{244690} 1030900;{22202};{217210} 1031130;{113135,113138,113132,113130,113 133,113127,113126,113131,113129,113136,113 125,113137,113134,113 128};{7700,7700,7700,7700,7700,7700,7700,7700,7700,191770,7700,7700,7700,7700} What I want to do, is where there are more than 5 rows involved in the aggregate, as in the last example, to split it into multiple rows of 5 aggregated rows. It's for a mailing list and I want to combine like addresses into one record, but if I'm over 5, I have to print the rest on a separate letter. 1031130;{113135,113138,113132,113130,113 133};{7700,7700,7700,7700,7700} 1031130;{113127,113126,113131,113129,113 136};{7700, 7700,7700,7700,191770} 1031130;{113125,113137,113134,113 128};{7700,7700,7700,7700} It looks like I should be able to use the window function to do this, but I've been unsuccessful. The following runs, but doesn't seem to have any effect: select owner_id, array_agg(trim(maplot)), array_agg(revallandvalue + revalbuildingvalues) from parcel group by owner_id window mywindow as (rows between current row and 5 following); Does anyone have any suggestions on what I should try? -Owen I didn't test it, but something along the lines of: select owner_id, array_agg(maplot), array_agg(totalvalues) from ( select owner_id, trim(maplot) as maplot, revallandvalue + revalbuildingvalues as totalvalues, row_number() over (partition by owner_id) as n from parcel ) q group by owner_id, (n - 1)/5; merlin -- Sent via pgsql-general mailing list (pgsql-general@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-general
Re: [GENERAL] SQL question on chunking aggregates
Merlin Moncure-2 wrote On Tue, Mar 4, 2014 at 1:49 PM, Owen Hartnett lt; owen@ gt; wrote: It looks like I should be able to use the window function to do this, but I've been unsuccessful. The following runs, but doesn't seem to have any effect: select owner_id, array_agg(trim(maplot)), array_agg(revallandvalue + revalbuildingvalues) from parcel group by owner_id window mywindow as (rows between current row and 5 following); Does anyone have any suggestions on what I should try? -Owen I didn't test it, but something along the lines of: select owner_id, array_agg(maplot), array_agg(totalvalues) from ( select owner_id, trim(maplot) as maplot, revallandvalue + revalbuildingvalues as totalvalues, row_number() over (partition by owner_id) as n from parcel ) q group by owner_id, (n - 1)/5; Yeah, a window cannot work because it cannot be defined to provide disjoint subsets. In most cases multiple invocations of array_agg(...) - at the same level in a query - will see the same row order but that is not something that it is wise to rely upon. Any time you want to have synchronized array_agg(...) calls you should add identical explicit ORDER BY clauses to them; or better yet combine that data into a custom datatype and then store that in the array. The solution is as Merlin presents; you need to use integer division to bucket the rows and then call the array_agg(...) using those groups. I like to keep the bucket ID around in order to capture the original order but as shown it is not a requirement. David J. -- View this message in context: http://postgresql.1045698.n5.nabble.com/SQL-question-on-chunking-aggregates-tp5794680p5794694.html Sent from the PostgreSQL - general mailing list archive at Nabble.com. -- Sent via pgsql-general mailing list (pgsql-general@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-general