Быстрый способ генерации сцепленных строк в Oracle - PullRequest
3 голосов
/ 23 сентября 2011

Разве мы не ненавидим, когда злое кодирование снова начинает преследовать?

Некоторое время назад мне нужно было сгенерировать строку, объединяющую некоторые поля для дальнейшей обработки позже. Я подумал, что это будет хорошей идеей, если прямо в запросе, и использовал помощь 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» я использую индекс.

ура

1 Ответ

6 голосов
/ 23 сентября 2011

Tom Kyte предоставляет очень удобный способ сделать это, и он работает с Oracle 9i, с пользовательской функцией агрегирования.Он объединяет запятые, но вы можете изменить тело функции для каналов.

Начиная с Oracle 11g, вы можете сделать:

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

Эта веб-страница предоставляет дополнительныеметоды, включая тот, который вы перечислили и который действительно не очень эффективен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...