![](/img/trans.png)
[英]REDSHIFT : SIZE below 65K BUT "error: Result size exceeds LISTAGG limit code: 8001"
[英]Using LISTAGG function in SQL causes error: Result size exceeds LISTAGG limit
我試圖在 SQL 中使用LISTAGG
函數,但LISTAGG
以下錯誤:
無效操作:結果大小超過 LISTAGG 限制詳細信息:
----------- 錯誤:結果大小超過 LISTAGG 限制代碼:8 ...
我如何擺脫這個錯誤?
請參閱https://docs.aws.amazon.com/redshift/latest/dg/r_LISTAGG.html 上的ListAgg 功能文檔
返回數據類型為 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"
列中超出的"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以字節(八位字節)為單位返回字符串的長度。
如您所見,與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
可用作 聚合函數或窗口函數,它將多行中的數據轉換為由指定分隔符分隔的單個值列表。 對於下面的示例,分隔符是,
(帶空格的逗號)。
下圖取自Oracle的Listagg函數-使用和重復刪除文章,它與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 函數和Window 函數都支持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' 已經被分成 2 部分,正如我們之前調查的那樣,同樣它被60000
分成了多個部分。
我們遇到的問題是數據庫限制。 因此,我們可以通過編程將LISTAGG
值合並到一個地方。 目前我沒有看到任何其他解決方案,或者在整個互聯網上找不到任何合適的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.