小编典典

在Oracle中生成串联字符串的快速方法

sql

当邪恶的编码再次困扰时,我们不讨厌吗?

前段时间,我需要生成一个字符串,将某些字段连接起来,以便稍后进行更多处理。我认为如果直接查询将是一个好主意,并使用SO的帮助来获取它。有效。一阵子…

桌子变得很大,现在这种技巧(我知道效率极低)并不完全可行。这是我在做什么:

with my_tabe as
(
    select 'user1' as usrid, '1' as prodcode from dual union
    select 'user1' as usrid, '2' as prodcode from dual union
    select 'user1' as usrid, '3' as prodcode from dual union
    select 'user2' as usrid, '2' as prodcode from dual union
    select 'user2' as usrid, '3' as prodcode from dual union
    select 'user2' as usrid, '4' as prodcode from dual
)
select
    usrid,
    ltrim(sys_connect_by_path(prodcode, '|'), '|') as prodcode
from 
    (
    select distinct prodcode, usrid,count(1)
    over (partition by usrid) as cnt,
    row_number() over (partition by usrid order by prodcode) as rn
    from my_tabe 
    )
where
    rn = cnt 
start with rn = 1
connect by prior rn + 1 = rn
and prior usrid = usrid

很好地产生:

USRID   PRODCODE
user1   1|2|3
user2   2|3|4

您可能已经注意到,这里的邪恶之处在于where rn = cnt,如果将其删除,您将看到Oracle真正在做的所有工作(我想):

USRID   PRODCODE
user1   1
user1   1|2
user1   1|2|3
user2   2
user2   2|3
user2   2|3|4

实际上,我在很多没有很多记录的地方都使用了此功能。多达五十万条记录是非常好的。

最近,我在具有〜15Mi记录的表中尝试了同样的操作,嗯…不好。

问题:是否有办法在Oracle上更有效地执行此操作,还是该将其归结为实际代码了?这不是实际的核心问题,因此,只要速度很快,我仍然可以负担得起。值得一提的是,我正在使用的“
usrid”列有一个索引。

干杯,


阅读 188

收藏
2021-05-05

共1个答案

小编典典

Tom
Kyte
提供了一种非常方便的方法来实现此目的,并且它从Oracle
9i开始具有自定义聚合功能。它使用逗号聚合,但是您可以修改管道的功能主体。

从Oracle 11g开始,您可以执行以下操作:

SELECT LISTAGG(column, separator) WITHIN GROUP (ORDER BY field)
  FROM dataSource
 GROUP BY grouping columns

该网页提供了其他方法,包括您列出的方法,但实际上效率不高。

2021-05-05