SQL连接多行

use*_*246 8 concat teradata partition

我正在使用Teradata,我有一张这样的桌子

ID       String
123      Jim
123      John
123      Jane
321      Jill
321      Janine
321      Johan
Run Code Online (Sandbox Code Playgroud)

我想查询表,所以我得到了

ID       String
123      Jim, John, Jane
321      Jill, Janine, Johan
Run Code Online (Sandbox Code Playgroud)

我试过分区,但可以有很多名字.我如何得到这个结果.甚至,指出我正确的方向将是伟大的.

dno*_*eth 8

不幸的是Teradata没有PIVOT(14.10只有TD_UNPIVOT).

如果运气好的话,你的站点会有一个聚合UDF进行组连接(可能性很小).

否则有两种选择:递归或聚合.

如果已知每个id的最大行数,则聚合通常更快.这是很多代码,但大多数是基于剪切和粘贴.

SELECT
  id,
     MAX(CASE WHEN rn = 1 THEN string END)
  || MAX(CASE WHEN rn = 2 THEN ',' || string ELSE '' END)
  || MAX(CASE WHEN rn = 3 THEN ',' || string ELSE '' END)
  || MAX(CASE WHEN rn = 4 THEN ',' || string ELSE '' END)
  || ... -- repeat up to the known maximum
FROM
 (
   SELECT
      id, string, 
      ROW_NUMBER() 
      OVER (PARTITION BY id
            ORDER BY string) AS rn
   FROM t
 ) AS dt
GROUP BY 1;
Run Code Online (Sandbox Code Playgroud)

对于大型表,当您首先使用GROUP BY列作为PI实现Volatile Table中的派生表的结果时,它会更有效.

对于递归,您也应该使用易失性表,因为递归部分中不允许OLAP函数.使用视图将重复计算OLAP功能,从而导致性能不佳.

CREATE VOLATILE TABLE vt AS
 (
   SELECT
      id
      ,string
      ,ROW_NUMBER()
       OVER (PARTITION BY id
             ORDER BY string DESC) AS rn -- reverse order!
      ,COUNT(*)
       OVER (PARTITION BY id) AS cnt
   FROM t
 ) WITH DATA 
UNIQUE PRIMARY INDEX(id, rn)
ON COMMIT PRESERVE ROWS;

WITH RECURSIVE cte
(id, list, rn) AS
 (
   SELECT
      id
      ,CAST(string AS VARCHAR(1000)) -- define maximum size based on maximum number of rows 
      ,rn
   FROM vt
   WHERE rn = cnt

   UNION ALL

   SELECT
      vt.id
      ,cte.list || ',' || vt.string
      ,vt.rn
   FROM vt
   JOIN cte
   ON vt.id = cte.id
   AND vt.rn = cte.rn - 1
)
SELECT id, list
FROM cte
WHERE rn = 1;
Run Code Online (Sandbox Code Playgroud)

这种方法存在一个问题,它可能需要大量的线轴,当您省略时很容易看到WHERE rn = 1.


小智 6

SELECT ID,  
TRIM(TRAILING ',' FROM (XMLAGG(TRIM(String)|| ',' ORDER BY String) (VARCHAR(10000)))) as Strings
FROM db.table
GROUP BY 1  
Run Code Online (Sandbox Code Playgroud)