{"id":784,"date":"2021-06-26T19:19:55","date_gmt":"2021-06-26T13:19:55","guid":{"rendered":"https:\/\/mellowhost.com\/blog\/?p=784"},"modified":"2021-06-26T19:22:52","modified_gmt":"2021-06-26T13:22:52","slug":"how-to-aggregate-column-with-a-different-value-in-an-array-using-group-in-postgresql","status":"publish","type":"post","link":"https:\/\/mellowhost.com\/blog\/how-to-aggregate-column-with-a-different-value-in-an-array-using-group-in-postgresql.html","title":{"rendered":"How to aggregate column with non-aggregable value in an Array using Group in PostgreSQL"},"content":{"rendered":"\n<p>Let&#8217;s imagine, scenario is like the following:<\/p>\n\n\n\n<p>We have three columns with the following values in a table named &#8216;sale_line&#8217;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">----------------------------------------\nproduct_id\tqty_done\tsale_id\n----------------------------------------\n1010\t\t5.0\t\t101\n1010\t\t1.0\t\t102\n1010\t\t2.0\t\t103\n1012\t\t1.0\t\t104\n1012\t\t4.0\t\t105\n1012\t\t4.0\t\t106\n1012\t\t9.0\t\t107<\/pre>\n\n\n\n<p>We have a product_id column that contains which product we are referring to, a qty_done column, which contains the number of products sold, and sale_id refers to the sale order where the product_id was dispatched. Now the example table contains how many of each product dispatched in different sale orders. We can write a query, to group the product_id and the total number of products sold using aggregation<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">select product_id, sum(qty_done) as total_sold from sale_line group by product_id;<\/pre>\n\n\n\n<p>The producing result would be the following:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">---------------------------\nproduct_id\ttotal_sold\n---------------------------\n1010\t\t8.0\t\t\n1012\t\t17.0\t<\/pre>\n\n\n\n<p>We can see, how group by can give you the benefit of aggregation. But have you noticed, we have a column called &#8216;sale_id&#8217; that doesn&#8217;t go with any aggregation function like &#8216;count&#8217;, &#8216;sum&#8217; or &#8216;avg&#8217;. Can we use them for any purpose? <\/p>\n\n\n\n<p>Sometimes, you may be interested to track down the orders responsible for a set of products using group by when each products will contain the list of orders responsible for causing the total sell. Can we accomplish that in one query?<\/p>\n\n\n\n<p>We actually can. We can concat distinct ids and put them in a resulting array instead of our known aggregation function like &#8216;count&#8217; or &#8216;sum&#8217;. Postgres provides a array aggregation function called &#8216;array_agg&#8217;, it can be used to produce such result. Have a look at the following query:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">select product_id, sum(qty_done) as total_sold, array_agg(sale_id) as sale_ids from sale_line group by product_id;<\/pre>\n\n\n\n<p>The producing result would be the following:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">-----------------------------------------\nproduct_id\ttotal_sold\tsale_ids\n-----------------------------------------\n1010\t\t8.0\t\t[101, 102, 103]\n1012\t\t17.0\t\t[104, 105, 106, 107]<\/pre>\n\n\n\n<p>As you can see, we have made postgres return us an array that contains the sale_ids for consisting total_sold even though, sale_id column wasn&#8217;t conventionally aggregable or let&#8217;s say different than the usual numeric pattern.<\/p>\n\n\n\n<p>This technique can have many use cases. For example if you have a different model\/table for managing sale orders, purchase orders, pickings and invoices while, your sale orders contains the price information, and the pickings doesn&#8217;t, but picking contains the actual number of products got dispatched, then you may first aggregate the total_sold from the picking table, then produce an average price using the sale_ids you have produced from the picking table using group by and array aggregation, then merge them. This seems quite complicated, I understand, but again, it&#8217;s all about putting a break to your reporting time, and manage scalability of your application, putting a constant cost based reporting algorithm using single sql query, even if you process 10 times more orders in future.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s imagine, scenario is like the following: We have three columns with the following values in a table named &#8216;sale_line&#8217; We have a product_id column that contains which product we are referring to, a qty_done column, which contains the number of products sold, and sale_id refers to the sale order where the product_id was dispatched. &hellip; <a href=\"https:\/\/mellowhost.com\/blog\/how-to-aggregate-column-with-a-different-value-in-an-array-using-group-in-postgresql.html\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;How to aggregate column with non-aggregable value in an Array using Group in PostgreSQL&#8221;<\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[412,292,523,271],"tags":[584,585,586,580,524],"_links":{"self":[{"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/posts\/784"}],"collection":[{"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/comments?post=784"}],"version-history":[{"count":3,"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/posts\/784\/revisions"}],"predecessor-version":[{"id":788,"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/posts\/784\/revisions\/788"}],"wp:attachment":[{"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/media?parent=784"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/categories?post=784"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mellowhost.com\/blog\/wp-json\/wp\/v2\/tags?post=784"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}