2014-11-25 2 views
0

У меня есть следующий набор данных:Объединить поля в один столбец

user_id | advr1_id | advr1_name | advr2_id | advr2_name | advr3_id | advr3_name 
--------+----------+------------+----------+------------+----------+----------- 
     7 |  22 | John Smith |  15 | Jane Doe |  9 | Bill Clint 
     8 |  15 | Jane Doe |  10 | Kim Gol |  null | null 

Я хочу сделать еще один столбец advrs, который содержит все имена advr (это было бы в размещенной в запись выше).

user_id | advrs 
--------+--------------------------------- 
     7 | John Smith; Jane Doe; Bill Clint 
     8 | Jane Doe; Kim Gol 

я могу добиться этого с listagg() но это супер медленный ... есть альтернативный метод, который я не знаю о?

+0

Я мог бы использовать 'advr1_name || «; '|| advr2_name'? Но нужен ли мне оператор case для учета нулевых значений или я могу каким-то образом использовать 'nvl()'? –

+0

Я пробовал этот метод, но он так же медленный, если не медленнее, чем listagg(). –

+0

Вы можете использовать [COALESCE] (https://docs.oracle.com/cd/B28359_01/server.111/b28286/functions023.htm#SQLRF00617) вместо nvl. Но я думаю, что вы должны рассмотреть свой набор данных, добавить фильтры диапазона или индексы, сам запрос медленный, список и случай, объединенный с coalesce, в вашем случае не помогут. – mikron

ответ

2

Что-то вроде этого, может быть:

select user_id, 
     replace(
      listagg(
       advr1_name 
       || decode(advr2_name, null, '', '# ' || advr2_name) 
       || decode(advr3_name, null, '', '# ' || advr3_name) 
       , '; ' 
       ) within group (order by advr1_name), 
      '#', ';' 
     ) 
from your_tab 
group by user_id;  
0

Не очень или очень эффективно, и не совсем масштабируемой, если вы когда-либо добавить advr4... или больше, но это может сделать работу быстрее, чем listagg:

ltrim(rtrim(replace(advr1_name||'; '||advr2_name||'; '||advr3_name, '; ; ', '; '), '; '),'; ') 
Смежные вопросы