有没有办法在 listagg() 用完 space (>4k) 后继续下一行?

Is there a way to continue on the next row after listagg() runs out of space (>4k)?

我想将每周有多个值的 table 更改为每周将所有值排在一行中。但是当我使用 listagg() 时,我 运行 超出了 space。我无法更改最大字符串大小 (ALTER SYSTEM SET max_string_size=extended SCOPE= SPFILE),并且我不想 t运行cate 结果字符串。但是我可以继续下一行,但我不确定该怎么做。例如,如果我的输入是:

Week                   SKU
202001                 598441
202001                 846541
202001                 77557
202001                 57813
202001                 5741651
202001                 21684135
202001                 5451516
202001                 545129
202001                 98754123
202001                 5644242
202002                 68454155
...

假设输入文件足够长,它会触发错误:

01489. 00000 -  "result of string concatenation is too long"
*Cause:    String concatenation result is more than the maximum size.
*Action:   Make sure that the result is less than the maximum size.

那我要一段类似这样的代码:

select 
  weeknr, 
  ''''||listagg(sku, ''',''', ON OVERFLOW NEXT LINE) within group(order by weeknr)||'''' sku_numbers
from 
  input_table
group by 
  weeknr

这样我的输出将如下所示:

Week                   SKU
202001                 '598441','846541','77557','57813','5741651','21684135'
202001                 '5451516','545129','98754123','5644242'
202002                 '68454155',...
...

这可能吗?非常感谢任何帮助!

由于LISTAGG有4000个字符的限制,切换到XML。我不认为你可以“强迫”LISTAGG 采取不同的行动。

SQL> SELECT LISTAGG (dname, ', ') WITHIN GROUP (ORDER BY dname) result FROM dept;

RESULT
--------------------------------------------------------------------------------
ACCOUNTING, OPERATIONS, RESEARCH, SALES

SQL>
SQL> SELECT RTRIM (
  2            XMLAGG (XMLELEMENT (e, dname || ', ') ORDER BY dname).EXTRACT (
  3               '//text()'),
  4            ', ') result
  5    FROM dept;

RESULT
--------------------------------------------------------------------------------
ACCOUNTING, OPERATIONS, RESEARCH, SALES

SQL>

您可以使用 MATCH_RECOGNIZE 逐行检查以查看字符串是否超过 4000 个字符,并将值分配给小于该字符的组,因此您可以使用 LISTAGG:

SELECT week,
       ''''||LISTAGG( sku, ''',''' ) WITHIN GROUP ( ORDER BY sku )||'''' AS skus
FROM   table_name
MATCH_RECOGNIZE (
  PARTITION BY Week
  ORDER     BY SKU
  MEASURES
    MATCH_NUMBER() AS mno
  ALL ROWS PER MATCH
  PATTERN ( concatenated_string+ )
  DEFINE
    concatenated_string AS SUM(LENGTH(SKU)+3)-1 <= 4000
)
GROUP BY week, mno

其中,对于示例数据:

CREATE TABLE table_name ( Week, SKU ) AS
SELECT *
FROM   (
  SELECT 202001 AS week, 10000000+LEVEL AS sku FROM DUAL CONNECT BY LEVEL <= 500
  UNION ALL
  SELECT 202002, 10000000+LEVEL FROM DUAL CONNECT BY LEVEL <= 100
)
ORDER BY week, DBMS_RANDOM.VALUE; -- put the rows into a random order in the table.

输出:

  WEEK | SKUS                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
-----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
202001 | '10000001','10000002','10000003','10000004','10000005','10000006','10000007','10000008','10000009','10000010','10000011','10000012','10000013','10000014','10000015','10000016','10000017','10000018','10000019','10000020','10000021','10000022','10000023','10000024','10000025','10000026','10000027','10000028','10000029','10000030','10000031','10000032','10000033','10000034','10000035','10000036','10000037','10000038','10000039','10000040','10000041','10000042','10000043','10000044','10000045','10000046','10000047','10000048','10000049','10000050','10000051','10000052','10000053','10000054','10000055','10000056','10000057','10000058','10000059','10000060','10000061','10000062','10000063','10000064','10000065','10000066','10000067','10000068','10000069','10000070','10000071','10000072','10000073','10000074','10000075','10000076','10000077','10000078','10000079','10000080','10000081','10000082','10000083','10000084','10000085','10000086','10000087','10000088','10000089','10000090','10000091','10000092','10000093','10000094','10000095','10000096','10000097','10000098','10000099','10000100','10000101','10000102','10000103','10000104','10000105','10000106','10000107','10000108','10000109','10000110','10000111','10000112','10000113','10000114','10000115','10000116','10000117','10000118','10000119','10000120','10000121','10000122','10000123','10000124','10000125','10000126','10000127','10000128','10000129','10000130','10000131','10000132','10000133','10000134','10000135','10000136','10000137','10000138','10000139','10000140','10000141','10000142','10000143','10000144','10000145','10000146','10000147','10000148','10000149','10000150','10000151','10000152','10000153','10000154','10000155','10000156','10000157','10000158','10000159','10000160','10000161','10000162','10000163','10000164','10000165','10000166','10000167','10000168','10000169','10000170','10000171','10000172','10000173','10000174','10000175','10000176','10000177','10000178','10000179','10000180','10000181','10000182','10000183','10000184','10000185','10000186','10000187','10000188','10000189','10000190','10000191','10000192','10000193','10000194','10000195','10000196','10000197','10000198','10000199','10000200','10000201','10000202','10000203','10000204','10000205','10000206','10000207','10000208','10000209','10000210','10000211','10000212','10000213','10000214','10000215','10000216','10000217','10000218','10000219','10000220','10000221','10000222','10000223','10000224','10000225','10000226','10000227','10000228','10000229','10000230','10000231','10000232','10000233','10000234','10000235','10000236','10000237','10000238','10000239','10000240','10000241','10000242','10000243','10000244','10000245','10000246','10000247','10000248','10000249','10000250','10000251','10000252','10000253','10000254','10000255','10000256','10000257','10000258','10000259','10000260','10000261','10000262','10000263','10000264','10000265','10000266','10000267','10000268','10000269','10000270','10000271','10000272','10000273','10000274','10000275','10000276','10000277','10000278','10000279','10000280','10000281','10000282','10000283','10000284','10000285','10000286','10000287','10000288','10000289','10000290','10000291','10000292','10000293','10000294','10000295','10000296','10000297','10000298','10000299','10000300','10000301','10000302','10000303','10000304','10000305','10000306','10000307','10000308','10000309','10000310','10000311','10000312','10000313','10000314','10000315','10000316','10000317','10000318','10000319','10000320','10000321','10000322','10000323','10000324','10000325','10000326','10000327','10000328','10000329','10000330','10000331','10000332','10000333','10000334','10000335','10000336','10000337','10000338','10000339','10000340','10000341','10000342','10000343','10000344','10000345','10000346','10000347','10000348','10000349','10000350','10000351','10000352','10000353','10000354','10000355','10000356','10000357','10000358','10000359','10000360','10000361','10000362','10000363'
202001 | '10000364','10000365','10000366','10000367','10000368','10000369','10000370','10000371','10000372','10000373','10000374','10000375','10000376','10000377','10000378','10000379','10000380','10000381','10000382','10000383','10000384','10000385','10000386','10000387','10000388','10000389','10000390','10000391','10000392','10000393','10000394','10000395','10000396','10000397','10000398','10000399','10000400','10000401','10000402','10000403','10000404','10000405','10000406','10000407','10000408','10000409','10000410','10000411','10000412','10000413','10000414','10000415','10000416','10000417','10000418','10000419','10000420','10000421','10000422','10000423','10000424','10000425','10000426','10000427','10000428','10000429','10000430','10000431','10000432','10000433','10000434','10000435','10000436','10000437','10000438','10000439','10000440','10000441','10000442','10000443','10000444','10000445','10000446','10000447','10000448','10000449','10000450','10000451','10000452','10000453','10000454','10000455','10000456','10000457','10000458','10000459','10000460','10000461','10000462','10000463','10000464','10000465','10000466','10000467','10000468','10000469','10000470','10000471','10000472','10000473','10000474','10000475','10000476','10000477','10000478','10000479','10000480','10000481','10000482','10000483','10000484','10000485','10000486','10000487','10000488','10000489','10000490','10000491','10000492','10000493','10000494','10000495','10000496','10000497','10000498','10000499','10000500'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
202002 | '10000001','10000002','10000003','10000004','10000005','10000006','10000007','10000008','10000009','10000010','10000011','10000012','10000013','10000014','10000015','10000016','10000017','10000018','10000019','10000020','10000021','10000022','10000023','10000024','10000025','10000026','10000027','10000028','10000029','10000030','10000031','10000032','10000033','10000034','10000035','10000036','10000037','10000038','10000039','10000040','10000041','10000042','10000043','10000044','10000045','10000046','10000047','10000048','10000049','10000050','10000051','10000052','10000053','10000054','10000055','10000056','10000057','10000058','10000059','10000060','10000061','10000062','10000063','10000064','10000065','10000066','10000067','10000068','10000069','10000070','10000071','10000072','10000073','10000074','10000075','10000076','10000077','10000078','10000079','10000080','10000081','10000082','10000083','10000084','10000085','10000086','10000087','10000088','10000089','10000090','10000091','10000092','10000093','10000094','10000095','10000096','10000097','10000098','10000099','10000100'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             

db<>fiddle here

您可以创建自己的函数:

CREATE OR REPLACE TYPE VARCHAR_TABLE_TYPE AS TABLE OF VARCHAR2(30000);

CREATE OR REPLACE FUNCTION JoinTable(tab IN VARCHAR_TABLE_TYPE, Joiner IN VARCHAR2) RETURN VARCHAR2 IS
    res VARCHAR2(30000); -- or even: res CLOB;
BEGIN
    IF tab IS NULL THEN 
        RETURN NULL; 
    END IF;
    IF tab.COUNT = 0 THEN 
        RETURN NULL; 
    END IF;
    
    FOR i IN tab.FIRST..tab.LAST-1 LOOP 
        res := res || tab(i) || Joiner; 
    END LOOP;
    RETURN res || tab(tab.LAST);
END JoinTable;

那么你可以这样使用它:

SELECT 
   JoinTable(
      CAST(MULTISET(SELECT sku FROM input_table order by weeknr) AS VARCHAR_TABLE_TYPE),
      ','
   ) as sku_numbers
from dual

您可以使用解析函数求出字符串长度的SUM,然后将其用于子分组,如下所示:

SELECT WEEKNR,
       '''' || LISTAGG(SKU, ''',''') WITHIN GROUP(ORDER BY WEEKNR) || '''' SKU_NUMBERS
  FROM (
    SELECT WEEKNR,
           FLOOR(SUM(LENGTH(SKU) + 3) 
                   OVER(PARTITION BY WEEKNR ORDER BY SKU) / 4000) AS GROUP_NUMBER,
           SKU
      FROM INPUT_TABLE
)
 GROUP BY WEEKNR, GROUP_NUMBER