如何使用列表agg设置最大值

时间:2018-10-28 10:18:06

标签: oracle

我已经阅读了其他问题和答案,它们对我的问题没有帮助。我问是否有一种方法可以限制listagg返回的结果数。

我正在使用此查询

HR-HR <80的任何婴儿 AS

[INFO] Analysis Complete (1 seconds)
[WARNING] 

One or more dependencies were identified with known vulnerabilities in test:

commons-email-1.1.jar (org.apache.commons:commons-email:1.1, cpe:/a:apache:commons_email:1.1) : CVE-2017-9801, CVE-2018-1294


See the dependency-check report for more details.

,我收到以下错误消息:

  

ORA-01489:字符串连接的结果太长

我已经在线研究了如何设置大小限制,但似乎无法使其正常工作。有人可以建议如何设置限制,以使其不超过50个字符。

1 个答案:

答案 0 :(得分:2)

在Oracle 12.2中,您可以在ON OVERFLOW ERROR中使用LISTAGG,例如:

LISTAGG(meas_value, '; ' ON OVERFLOW ERROR) WITHIN GROUP (ORDER BY fm.recorded_time) 

然后,您可以用SUBSTR()括起来以获取前50个字符。

在12.2之前的版本中,您需要重组查询以限制LISTAGG看到的行数。这是一个使用DBA_OBJECTS的示例(因此没有您的表的人可以运行它)。对于每种对象类型,它只会显示第三个值。

SELECT object_type, 
       listagg(object_name, ', ') within group ( order by object_name) first_three
FROM (
    SELECT object_type, 
           object_name, 
           row_number() over ( partition by object_type order by object_name ) ord
    FROM   dba_objects
    WHERE  owner = 'SYS'
    )
WHERE ord <= 3
GROUP BY object_type
ORDER BY object_type;

想法是对要聚合的行进行编号,然后仅对其中的第一个X进行聚合,其中“ X”足够小,不会溢出VARCHAR2上的最大长度。 “ X”取决于您的数据。

或者,如果您不希望中间值出现50个字符的截断和/或不知道可以安全地允许多少个值,则可以将ord表达式替换为{ {1}}表达式以保持长度的连续计数,并在达到您的限制(50个字符)之前将其限制为上限。该表达式将为running_length。像这样:

SUM(length()) OVER (...)

对于您的查询,所有内容汇总如下:

SELECT object_type, 
       listagg(object_name, ', ') within group ( order by object_name) first_50_char,
FROM (
    SELECT object_type, 
           object_name, 
           sum(length(object_name || ', ')) 
              over ( partition by object_type order by object_name ) running_len
    FROM   dba_objects
    WHERE  owner = 'SYS'
    )
WHERE running_len <= 50+2  -- +2 because the last one won't have a trailing delimiter
GROUP BY object_type
ORDER BY object_type;
相关问题