在 SQL 中附加值

Append values in SQL

假设我有下一个table。

我在附加位于不同行的值时遇到以下问题。

rankk val price
1   A   10
2   B   20
3   C   30

我怎样才能得到这个结果?

rank val2
1    A
2    A,B
3    A,B,C

我坚持

rank val2
1    A
2    ,B
3    ,C

create multiset volatile table tmp_db (
rankk integer,
val varchar(1),
price integer)
primary index (val) on commit preserve rows;

insert into tmp_db values (1,'A',10);
insert into tmp_db values (2,'B',20);
insert into tmp_db values (3,'C',30);

sel rankk,
        max(case when rankk = 1 then val else '' end) ||
        max(case when rankk = 2 then ',' || val else '' end) ||
        max(case when rankk = 3 then ',' || val else '' end) as val2,
        avg(price) as avg_price

from   tmp_db
group by 1;

在此先感谢给您带来的不便。

你需要这样的自连接

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(这将在值之间添加 space):

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

尝试使用递归 cte

with combo_data
  as (select rankk,val, cast(val as varchar(100)) as val2
        from tmp_db 
       where rankk=1
      union all
      select b.rankk,b.val,cast(concat(b.val,',',a.val2) as varchar(100))
        from tmp_db b
        join combo_data a
          on a.rankk+1=b.rankk
      )
select rankk,val2
  from combo_data