Amazon redshift 在Amazon Redshift上管理Listag中的溢出

Amazon redshift 在Amazon Redshift上管理Listag中的溢出,amazon-redshift,listagg,Amazon Redshift,Listagg,使用本文中的示例: 声明如下: SELECT deptno, LISTAGG(ename, ';') WITHIN GROUP (ORDER BY empno) AS namelist FROM emp GROUP BY deptno; 将生成以下输出: DEPTNO NAMELIST ---------- ---------------------------------------- 10 CLARK;KING;MILLER 20 SMITH;J

使用本文中的示例:

声明如下:

SELECT
deptno,
LISTAGG(ename, ';') WITHIN GROUP (ORDER BY empno) AS namelist 
FROM emp 
GROUP BY deptno;
将生成以下输出:

DEPTNO     NAMELIST
---------- ----------------------------------------
10         CLARK;KING;MILLER
20         SMITH;JONES;SCOTT;ADAMS;FORD
30         ALLEN;WARD;MARTIN;BLAKE;TURNER;JAMES
让我们假设上面的语句没有运行,并且LISTAGG函数中的每一行最多只能返回15个字符。这实际上是亚马逊红移上的65535

在这种情况下,我们希望返回以下内容:

DEPTNO     NAMELIST
---------- ----------------------------------------
10         CLARK;KING
10         MILLER
20         SMITH;JONES
20         SCOTT;ADAMS
20         FORD
30         ALLEN;WARD
30         MARTIN;BLAKE
30         TURNER;JAMES 

在Amazon Redshift中重新创建此结果的最佳方法是什么,以避免任何数据丢失并考虑速度?

可以创建一个部分列表,然后一次性将其余的值作为单独的行,但如果行数不受限制,则确实需要一个循环语句将其转换为列表,和剩余的行,依此类推


所以这确实是ApacheSpark(或任何其他MapReduce技术)的任务

可以通过两个子查询实现这一点:

第一:

SELECT id, field,
       sum(length(field) + 1) over 
       (partition by id order by RANDOM() rows unbounded preceding) as total_length_now
    from my_schema.my_table)
首先,我们要计算表中每个id的字符数。我们可以使用窗口函数为每一行递增计算它。在“order by”语句中,您可以使用您拥有的任何唯一字段。如果没有,您可以简单地使用random或hash函数,但必须确保字段是唯一的,否则,函数将无法按我们的要求工作

长度中的“+1”表示我们将在listagg函数中使用的分号

第二:

SELECT id, field, total_length_now / 65535 as sub_id
FROM (sub_query_1)
现在,我们根据之前计算的长度创建一个sub_id。如果总长度现在超过限制大小(在本例中为65535),则分区的其余部分将返回一个新的sub_id

最后一步

SELECT id, sub_id, listagg(field, ';') as namelist
FROM (sub_query_2)
GROUP BY id, sub_id
ORDER BY id, sub_id
现在我们可以简单地调用listagg函数,按id和sub_id分组,因为每个组都不能超过大小限制

完整查询

SELECT id, sub_id, listagg(field, ';') as namelist
FROM (
SELECT id, field, total_length_now / 65535 as sub_id
FROM (SELECT id,
       field,
       sum(length(field) + 1) over 
       (partition by id order by field rows unbounded preceding) as total_length_now
from support.test))
GROUP BY id, sub_id
order by id, sub_id
数据示例(大小限制=10)

第一个和第二个查询输出:

id, field, total_length_now, sub_id

10,KING,5,0
10,CLARK,11,1
10,MILLER,18,1
20,ADAMS,6,0
20,SMITH,12,1
20,JONES,18,1
20,FORD,23,2
20,SCOTT,29,2
30,JAMES,6,0
30,BLAKE,12,1
30,WARD,17,1
30,MARTIN,24,2
30,TURNER,31,3
30,ALLEN,37,3
id,sub_id,namelist

10,0,KING
10,1,CLARK;MILLER
20,0,ADAMS
20,1,SMITH;JONES
20,2,FORD;SCOTT
30,0,JAMES
30,1,BLAKE;WARD
30,2,MARTIN
30,3,TURNER;ALLEN
最终查询输出:

id, field, total_length_now, sub_id

10,KING,5,0
10,CLARK,11,1
10,MILLER,18,1
20,ADAMS,6,0
20,SMITH,12,1
20,JONES,18,1
20,FORD,23,2
20,SCOTT,29,2
30,JAMES,6,0
30,BLAKE,12,1
30,WARD,17,1
30,MARTIN,24,2
30,TURNER,31,3
30,ALLEN,37,3
id,sub_id,namelist

10,0,KING
10,1,CLARK;MILLER
20,0,ADAMS
20,1,SMITH;JONES
20,2,FORD;SCOTT
30,0,JAMES
30,1,BLAKE;WARD
30,2,MARTIN
30,3,TURNER;ALLEN

差不多5年了,这看起来不错!在接受你的回答之前,我会再开放一周。谢谢,我一周前刚刚看到你的问题,这是一个很好的问题:)很好的解决方案,以及我碰巧需要的。。。但红移需要我们求助于此,这让我们感到羞耻……我想建议修改Hyruma92的解决方案。由于某些字符大于1字节,因此最好使用返回字节数的长度,而不是返回字符数的长度。