Using LISTAGG function in SQL causes error: Result size exceeds LISTAGG limit
Using LISTAGG function in SQL causes error: Result size exceeds LISTAGG limit
我试图在 SQL 中使用 LISTAGG
函数,但遇到以下错误:
Invalid operation: Result size exceeds LISTAGG limit Details:
----------- error: Result size exceeds LISTAGG limit code: 8 ...
如何摆脱这个错误?
请参阅 https://docs.aws.amazon.com/redshift/latest/dg/r_LISTAGG.html
处的 ListAgg 函数文档
return 数据类型为 varchar(max),即 64K varchar 大小
你描述的错误在官方文档中完全有提到
你可以考虑使用 ListAgg() 函数和 Distinct 如下来减少要连接的项目
select listagg(distinct sellerid, ', ') within group (order by sellerid) from sales
where eventid = 4337;
这就是我们遇到问题的原因。
这是我尝试执行的 SQL 查询,
SELECT DISTINCT "year_level", LISTAGG("value", ', ') WITHIN GROUP (ORDER BY "year_level") OVER (PARTITION BY "year_level")
FROM "school_1__acara_db"."acara_data_set";
这是我得到的错误。
ERROR: Result size exceeds LISTAGG limit Detail: ----------------------------------------------- error: Result size exceeds LISTAGG limit code: 8001 context: LISTAGG limit: 65535 query: 4360256 location: string_ops.cpp:116 process: query1_127_4360256 [pid=1793] -----------------------------------------------
让我们把这个问题分成几个小部分。所以正如他们提到的,我已经超过了 LISTAGG
的最大限制。我们可以通过下面的 SQL 查询根据 "year_level"
.
找到 "value"
列中超出的值
SELECT "year_level", SUM(OCTET_LENGTH("value")) as total_bytes
FROM "school_1__acara_db"."acara_data_set"
GROUP BY "year_level"
ORDER BY total_bytes;
这是输出。
OCTET_LENGTH returns 以字节(八位字节)为单位的字符串长度。
如您所见,与 Primary Ungraded
相关的值的总字节数为 50329
,而 Secondary Ungraded
的总字节数为 61178
。两者均未超过 VARCHAR(MAX)
、65535
限制。至少我可以得到以上两条记录的 LISTAGG
值吗?这是我要执行的查询,
SELECT DISTINCT "year_level", LISTAGG("value", ', ') WITHIN GROUP (ORDER BY "year_level") OVER (PARTITION BY "year_level")
FROM "school_1__acara_db"."acara_data_set"
WHERE "year_level" IN ('Primary Ungraded', 'Secondary Ungraded');
我遇到了同样的错误,Result size exceeds LISTAGG limit Detail: -----------
。正如我们在上面的结果中看到的那样,它没有超过 VARCHAR(MAX)
、65535
的限制。但为什么?让我们通过以下查询查看与 "year_level"
相关的 "value"
列计数。
SELECT "year_level", COUNT("value") as total_counts
FROM "school_1__acara_db"."acara_data_set"
GROUP BY "year_level"
ORDER BY total_counts;
这是输出。
在进一步解释之前,让我们看看 LISTAGG
是如何工作的。
在 Redshift 中,LISTAGG
可用作 Aggregate function or a Window function,它将来自多行的数据转换为由指定分隔符分隔的单个值列表。对于下面的示例,分隔符是 ,
(带空格的逗号)。
下图摘自Oracle's Listagg Function - Uses and Duplicate Removal文章,与Oracle有关,但可以得到LISTAGG
函数的基本概念。
这就是数据与分隔符合并的方式。
甚至我们的查询也使用分隔符 ,
(带空格的逗号)。我们以获取下图中的第一条记录为例。
"Primary Ungraded"
有 3412
条记录,总字节数为 50329
。所以这意味着我们要将 3412
条记录合并到一个列中。当我们合并时,它应该有 50329
的总字节数。但是我们不是直接合并,我们是用分隔符合并。因此 3412
条记录之间有 3411
个分隔符。
delimiter_count = no_of_records - 1
如果不明白,请查看 Example #1
如何合并数据的图像。所以根据这个,当我们 运行 我们最后一个没有分隔符的失败查询时,它应该可以工作。
SELECT DISTINCT "year_level", LISTAGG("value", '') WITHIN GROUP (ORDER BY "year_level") OVER (PARTITION BY "year_level")
FROM "school_1__acara_db"."acara_data_set"
WHERE "year_level" IN ('Primary Ungraded', 'Secondary Ungraded')
是的,它工作正常。但这对其他记录不起作用,因为它们不做任何事情就已经超过了 VARCHAR(MAX)
、65535
限制。
很多人建议在 LISTAGG
函数中使用 DISTINCT
关键字。 Aggregate function and Window function 都支持 DISTINCT
关键字作为可选。
LISTAGG( [DISTINCT] aggregate_expression [, 'delimiter' ] )
[ WITHIN GROUP (ORDER BY order_list) ]
LISTAGG( [DISTINCT] expression [, 'delimiter' ] )
[ WITHIN GROUP (ORDER BY order_list) ]
OVER ( [PARTITION BY partition_expression] )
没有重复,我有超过 VARCHAR(MAX)
、65535
限制的数据。所以我不能在我的情况下使用它。
我们不能将数据分成更小的部分吗?是的,我们可以用下面的查询来完成,不要混淆,下面的解决方案是由我的一位名叫 Isuru 的队友找到的。
SELECT year_level, num_of_parts, listagg(value,',') AS listagg_data FROM (
SELECT year_level, value, total_bytes / 60000 AS num_of_parts FROM (
SELECT year_level, value, SUM(OCTET_LENGTH(value)) OVER (PARTION BY year_level ORDER BY value ROWS UNBOUNDED PRECEDING) AS total_bytes
FROM "school_1__acara_db"."acara_data_set"
)
)
GROUP BY year_level, num_of_parts
ORDER BY year_level, num_of_parts;
这是输出。
使用它你可以获取所有你想要的信息。在这里,我们将 total_bytes
按 60000
切片,可以看到在 num_of_parts
列中有多少块被破坏了。 'Primary Ungraded'
没有分割成任何部分,'Secondary Ungraded' 被分割成两部分,正如我们之前调查的那样,同样它被 60000
分割成多个部分。
我们遇到的问题是数据库限制。因此,我们可以通过编程方式将 LISTAGG
值合并到一个地方。目前我没有看到任何其他解决方案或无法在整个互联网上找到任何合适的解决方案。
我试图在 SQL 中使用 LISTAGG
函数,但遇到以下错误:
Invalid operation: Result size exceeds LISTAGG limit Details:
----------- error: Result size exceeds LISTAGG limit code: 8 ...
如何摆脱这个错误?
请参阅 https://docs.aws.amazon.com/redshift/latest/dg/r_LISTAGG.html
处的 ListAgg 函数文档return 数据类型为 varchar(max),即 64K varchar 大小
你描述的错误在官方文档中完全有提到
你可以考虑使用 ListAgg() 函数和 Distinct 如下来减少要连接的项目
select listagg(distinct sellerid, ', ') within group (order by sellerid) from sales
where eventid = 4337;
这就是我们遇到问题的原因。
这是我尝试执行的 SQL 查询,
SELECT DISTINCT "year_level", LISTAGG("value", ', ') WITHIN GROUP (ORDER BY "year_level") OVER (PARTITION BY "year_level")
FROM "school_1__acara_db"."acara_data_set";
这是我得到的错误。
ERROR: Result size exceeds LISTAGG limit Detail: ----------------------------------------------- error: Result size exceeds LISTAGG limit code: 8001 context: LISTAGG limit: 65535 query: 4360256 location: string_ops.cpp:116 process: query1_127_4360256 [pid=1793] -----------------------------------------------
让我们把这个问题分成几个小部分。所以正如他们提到的,我已经超过了 LISTAGG
的最大限制。我们可以通过下面的 SQL 查询根据 "year_level"
.
"value"
列中超出的值
SELECT "year_level", SUM(OCTET_LENGTH("value")) as total_bytes
FROM "school_1__acara_db"."acara_data_set"
GROUP BY "year_level"
ORDER BY total_bytes;
这是输出。
OCTET_LENGTH returns 以字节(八位字节)为单位的字符串长度。
如您所见,与 Primary Ungraded
相关的值的总字节数为 50329
,而 Secondary Ungraded
的总字节数为 61178
。两者均未超过 VARCHAR(MAX)
、65535
限制。至少我可以得到以上两条记录的 LISTAGG
值吗?这是我要执行的查询,
SELECT DISTINCT "year_level", LISTAGG("value", ', ') WITHIN GROUP (ORDER BY "year_level") OVER (PARTITION BY "year_level")
FROM "school_1__acara_db"."acara_data_set"
WHERE "year_level" IN ('Primary Ungraded', 'Secondary Ungraded');
我遇到了同样的错误,Result size exceeds LISTAGG limit Detail: -----------
。正如我们在上面的结果中看到的那样,它没有超过 VARCHAR(MAX)
、65535
的限制。但为什么?让我们通过以下查询查看与 "year_level"
相关的 "value"
列计数。
SELECT "year_level", COUNT("value") as total_counts
FROM "school_1__acara_db"."acara_data_set"
GROUP BY "year_level"
ORDER BY total_counts;
这是输出。
在进一步解释之前,让我们看看 LISTAGG
是如何工作的。
在 Redshift 中,LISTAGG
可用作 Aggregate function or a Window function,它将来自多行的数据转换为由指定分隔符分隔的单个值列表。对于下面的示例,分隔符是 ,
(带空格的逗号)。
下图摘自Oracle's Listagg Function - Uses and Duplicate Removal文章,与Oracle有关,但可以得到LISTAGG
函数的基本概念。
这就是数据与分隔符合并的方式。
甚至我们的查询也使用分隔符 ,
(带空格的逗号)。我们以获取下图中的第一条记录为例。
"Primary Ungraded"
有 3412
条记录,总字节数为 50329
。所以这意味着我们要将 3412
条记录合并到一个列中。当我们合并时,它应该有 50329
的总字节数。但是我们不是直接合并,我们是用分隔符合并。因此 3412
条记录之间有 3411
个分隔符。
delimiter_count = no_of_records - 1
如果不明白,请查看 Example #1
如何合并数据的图像。所以根据这个,当我们 运行 我们最后一个没有分隔符的失败查询时,它应该可以工作。
SELECT DISTINCT "year_level", LISTAGG("value", '') WITHIN GROUP (ORDER BY "year_level") OVER (PARTITION BY "year_level")
FROM "school_1__acara_db"."acara_data_set"
WHERE "year_level" IN ('Primary Ungraded', 'Secondary Ungraded')
是的,它工作正常。但这对其他记录不起作用,因为它们不做任何事情就已经超过了 VARCHAR(MAX)
、65535
限制。
很多人建议在 LISTAGG
函数中使用 DISTINCT
关键字。 Aggregate function and Window function 都支持 DISTINCT
关键字作为可选。
LISTAGG( [DISTINCT] aggregate_expression [, 'delimiter' ] )
[ WITHIN GROUP (ORDER BY order_list) ]
LISTAGG( [DISTINCT] expression [, 'delimiter' ] )
[ WITHIN GROUP (ORDER BY order_list) ]
OVER ( [PARTITION BY partition_expression] )
没有重复,我有超过 VARCHAR(MAX)
、65535
限制的数据。所以我不能在我的情况下使用它。
我们不能将数据分成更小的部分吗?是的,我们可以用下面的查询来完成,不要混淆,下面的解决方案是由我的一位名叫 Isuru 的队友找到的。
SELECT year_level, num_of_parts, listagg(value,',') AS listagg_data FROM (
SELECT year_level, value, total_bytes / 60000 AS num_of_parts FROM (
SELECT year_level, value, SUM(OCTET_LENGTH(value)) OVER (PARTION BY year_level ORDER BY value ROWS UNBOUNDED PRECEDING) AS total_bytes
FROM "school_1__acara_db"."acara_data_set"
)
)
GROUP BY year_level, num_of_parts
ORDER BY year_level, num_of_parts;
这是输出。
使用它你可以获取所有你想要的信息。在这里,我们将 total_bytes
按 60000
切片,可以看到在 num_of_parts
列中有多少块被破坏了。 'Primary Ungraded'
没有分割成任何部分,'Secondary Ungraded' 被分割成两部分,正如我们之前调查的那样,同样它被 60000
分割成多个部分。
我们遇到的问题是数据库限制。因此,我们可以通过编程方式将 LISTAGG
值合并到一个地方。目前我没有看到任何其他解决方案或无法在整个互联网上找到任何合适的解决方案。