Вам необходимо самообъединение, подобное этому
SEL t1.rankk,
Max(CASE WHEN t2.rankk = 1 THEN t2.val ELSE '' end) ||
Max(CASE WHEN t2.rankk = 2 THEN ',' || t2.val ELSE '' end) ||
Max(CASE WHEN t2.rankk = 3 THEN ',' || t2.val ELSE '' end) AS val2,
Avg(t2.price) AS avg_price
FROM tmp_db AS t1 JOIN tmp_db AS t2
ON t1.rankk >= t2.rankk -- include all previous rows
GROUP BY 1;
Для более высоких рангов также можно использовать xmlagg
(это добавит пробел между значениями):
SELECT t1.rankk,
Trim(Trailing ',' FROM
(XmlAgg(Trim(t2.val)|| ',' ORDER BY t2.val DESC) (VARCHAR(1000)))) AS val,
Avg(t2.price) AS avg_price
FROM tmp_db AS t1 JOIN tmp_db AS t2
ON t1.rankk >= t2.rankk
GROUP BY 1
В зависимости от ваших реальных данных вы также можете использовать рекурсию:
WITH RECURSIVE cte AS
(
SELECT rankk, val, Cast(val AS VARCHAR(1000)) AS rslt, price
FROM tmp_db
WHERE rankk = 1 -- start with 1st rank
UNION ALL
SELECT t.rankk, t.val,
cte.rslt || ',' || t.val AS rslt,
cte.price + t.price -- to calculate average using sum/rankk
FROM tmp_db AS t JOIN cte
ON t.rankk = cte.rankk+1
)
SELECT rankk, rslt, price / rankk
FROM cte