Aggregating rows with rank or index >= N Aggregating rows with rank or index >= N postgresql postgresql

Aggregating rows with rank or index >= N


If I understood you correctly, you can achieve this with CASE EXPRESSION :

SELECT customer_id,min(order_id),min(order_ts), CASE WHEN rnk < 5 then rnk else 5 end as rnk,sum(amount)FROM(    SELECT customer_id,            order_id,            order_ts,            RANK() OVER (PARTITION BY customer_id ORDER BY order_ts ASC) as rnk,            amount     FROM jq)GROUP BY customer_id,         CASE WHEN rnk < 5 then rnk else 5 endORDER BY customer_id

This will group each rnk > 5 as 5, so as 1 group. I selected min order_id,ts to select it form the 5th.


Though this produces the correct result, sagi's answer is more efficient.


You can use a SELECT on the result and filter for RANK < 5. Then do a UNION ALL on the aggregated values for RANK >= 5

WITH Cte AS(    SELECT         customer_id,         order_id,         order_ts,         RANK() OVER (PARTITION BY customer_id ORDER BY order_ts ASC) AS rnk,         amount     FROM jq     GROUP BY customer_id )SELECT    customer_id,    order_id,    order_ts,    rnk,    amountFROM CteWHERE rnk < 5UNION ALLSELECT    customer_id,    MIN(order_id),    MIN(order_ts),    MIN(rnk),    SUM(amount)FROM CteWHERE rnk >= 5GROUP BY customer_idORDER BY customer_id;

*This is for SQL Server


Try something like this, use an outer query to get the result

SELECT customer_id,(CASE WHEN ROW_NO <5 THEN ROW_NO ELSE 5 END) ROW_NO, SUM(amount) amountFROM (    SELECT customer_id,            order_id,            order_ts,            RANK() OVER (PARTITION BY customer_id ORDER BY order_ts ASC) ROW_NO,        amount FROM jq )   DGROUP BY customer_id,(CASE WHEN ROW_NO <5 THEN ROW_NO ELSE 5 END)