簡體   English   中英

在 SQL 中使用 LISTAGG 函數會導致錯誤:結果大小超出 LISTAGG 限制

[英]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相關的值的總字節數為50329Secondary 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM