在SQL中附加值

时间:2018-12-04 05:08:32

标签: sql append teradata

假设我有一张桌子。

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

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;

不便之处,敬请原谅。

2 个答案:

答案 0 :(得分: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(这将在值之间添加一个空格):

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

答案 1 :(得分:1)

尝试使用递归cte

# for python 2.7
import string
import win32api

def getfreedriveletter():
    """ Find first free drive letter """
    assigneddrives = win32api.GetLogicalDriveStrings().split('\000')[:-1]
    assigneddrives = [item.rstrip(':\\').lower() for item in assigneddrives]
    for driveletter in list(string.ascii_lowercase[2:]):
        if not driveletter in assigneddrives:
            return driveletter.upper() + ':'