2011-09-23 81 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線程中。 –