在 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
假设我有下一个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