2011-09-23 59 views
3

难道我们不讨厌恶意编码何时回到困境?在Oracle中快速生成连接字符串的方法

前段时间我需要生成一个字符串连接一些字段,以便稍后进行更多的处理。我认为在查询中直接做是个好主意,并使用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,如果你删除它,你会看到所有工作(我想)甲骨文真的这样做:

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

我实际上在很多地方使用这个,我没有这么多的记录。这是相当好的,大约有50万条记录。

最近我在~15Mi记录的表中尝试了同样的方式,并且没有什么好处。

问题:有没有办法在Oracle上更有效地做到这一点,或者是否有时间把它放到实际的代码中? 这不是真正的核心问题,所以我仍然可以负担kludging,只要它很快... 值得一提的是我使用的列“usrid”的索引。

欢呼声,

回答

6

Tom Kyte提供了一个非常方便的方式来做到这一点,并从Oracle 9i的作品,用自定义聚合功能。它用逗号聚合,但可以修改管道的函数体。

用的Oracle 11g开始,你可以这样做:

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

This web page提供更多的方法包括您列出,这确实是不是真的有效的一个。

+3

如果您使用10g,COLLECT方法比STRAGG快得多。有关详细信息,请参阅此处:http://www.oracle-developer.net/display.php?id=306#8fd65此方法也列在同一个Ask Tom线程中。 –