SQL连接多行

问题描述 投票:6回答:2

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

ID       String
123      Jim
123      John
123      Jane
321      Jill
321      Janine
321      Johan

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

ID       String
123      Jim, John, Jane
321      Jill, Janine, Johan

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

teradata concat partition
2个回答
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;

对于大型表,当您首先使用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;

这种方法存在一个问题,它可能需要很多线轴,当你省略WHERE rn = 1时很容易看到。


2
投票
SELECT ID,  
TRIM(TRAILING ',' FROM (XMLAGG(TRIM(String)|| ',' ORDER BY String) (VARCHAR(10000)))) as Strings
FROM db.table
GROUP BY 1  
© www.soinside.com 2019 - 2024. All rights reserved.