3

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

前段时间我需要生成一个连接一些字段的字符串,以便稍后进行更多处理。我认为如果直接在查询中这样做是个好主意,并使用 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

我实际上在很多我没有太多记录的地方使用它。大约有 50 万条记录是相当不错的。

最近我在一张有~15Mi 记录的表中尝试了同样的方法,而且……不好。

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

干杯,

4

1 回答 1

6

Tom Kyte提供了一种非常方便的方法来实现这一点,它在 Oracle 9i 上运行,具有自定义聚合功能。它用逗号聚合,但您可以修改管道的函数体。

从 Oracle 11g 开始,您可以:

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

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

于 2011-09-23T14:58:22.603 回答