WITH t AS ( SELECT 'A' cod, 5000 amt FROM dual UNION ALL SELECT 'B', 4000 FROM dual UNION ALL SELECT 'C', 4000 FROM dual UNION ALL SELECT 'D', 3000 FROM dual UNION ALL SELECT 'E', 3000 FROM dual UNION ALL SELECT 'F', 3000 FROM dual UNION ALL SELECT 'G', 2000 FROM dual UNION ALL SELECT 'H', 2000 FROM dual UNION ALL SELECT 'I', 2000 FROM dual UNION ALL SELECT 'J', 2000 FROM dual UNION ALL SELECT 'K', 1000 FROM dual UNION ALL SELECT 'L', 1000 FROM dual UNION ALL SELECT 'M', 1000 FROM dual UNION ALL SELECT 'N', 1000 FROM dual UNION ALL SELECT 'O', 1000 FROM dual UNION ALL SELECT 'P', 500 FROM dual UNION ALL SELECT 'Q', 500 FROM dual ) , t1(cod, amt, cnt, cods, amts, tot) AS ( SELECT cod , amt , 1 cnt , CAST(cod AS VARCHAR2(4000)) cods , CAST(amt AS VARCHAR2(4000)) amts , amt tot FROM t WHERE amt < 5000 UNION ALL SELECT c.cod , c.amt , DECODE(p.cod, c.cod, p.cnt+1, 1) cnt , DECODE(p.cod, c.cod, REGEXP_REPLACE(p.cods, '[*][0-9]+$')||'*'||(p.cnt+1), p.cods||'+'||c.cod) cods , DECODE(p.cod, c.cod, REGEXP_REPLACE(p.amts, '[*][0-9]+$')||'*'||(p.cnt+1), p.amts||'+'||c.amt) amts , p.tot + c.amt tot FROM t c , t1 p WHERE p.tot + c.amt < 5000 AND p.cod <= c.cod ) SELECT cods , amts , tot FROM t1 ;