2016-12-09 2 views
3

У меня есть столбец, который имеет несколько пунктов, в которых мне нужно подсчитать раз его называют, мой столбец таблицы выглядит следующим образом:подстроки в колонке

Table Example

Id_TR    Triggered 
--------------  ------------------ 
A1_6547    R1:23;R2:0;R4:9000 
A2_1235    R2:0;R2:100;R3:-100 
A3_5436    R1:23;R2:100;R4:9000 
A4_1245    R2:0;R5:150 

И я бы как результат, чтобы быть похожим на это:

Expected Results

Triggered   Count(1) 
--------------- -------- 
R1:23    2 
R2:0    3 
R2:100    2 
R3:-100    1 
R4:9000    2 
R5:150    1 

Я попытался сделать некоторую подстроку, но, похоже, не нашел, как решить эту проблему. Может ли кто-нибудь помочь?

+0

Пожалуйста, замените изображения с текстом (используйте ctrl-K, чтобы сохранить формат) –

+0

это синтаксический анализ регулярного выражения - и, пожалуйста, скажите дизайнеру таблицы, чтобы он никогда не проектировался так снова. – Randy

+0

Да, я знаю, что это головная боль, чтобы получить данные! – Zombraz

ответ

1

Это решение раз X3 быстрее, чем CONNECT BY решения

производительность: 15K записей в секунду

with  cte (token,suffix) 
      as 
      (
       select  substr(triggered||';',1,instr(triggered,';')-1)  as token 
          ,substr(triggered||';',instr(triggered,';')+1)  as suffix 

       from  t 

       union all 

       select  substr(suffix,1,instr(suffix,';')-1)  as token 
          ,substr(suffix,instr(suffix,';')+1)  as suffix 

       from  cte 

       where  suffix is not null 

      ) 

select  token,count(*) 
from  cte 
group by token 
;   
+0

Работы действительно хороший! И он посылает мне результаты в секундах, я оцениваю выходные данные, но все, кажется, работает просто отлично! Спасибо огромное! – Zombraz

+0

Отлично: -) ...... –

1

Это только для учебных целей.
Проверьте мои другие решения.

производительность: 1K записей в секунду

select  x.triggered 
      ,count(*) 

from  t 
      ,xmltable 
      (
       '/r/x' 
       passing xmltype('<r><x>' || replace(triggered,';', '</x><x>') || '</x></r>') 
       columns triggered varchar(100) path '.' 
      ) x 

group by x.triggered 
; 
+0

Я пробовал эту опцию и пока так хорош, просто проверяю фактические данные на столе. – Zombraz

0

Это справедливое решение.

производительность: 5K записей в секунду

select  triggered 
      ,count(*)   as cnt 

from  (select  id_tr 
         ,regexp_substr(triggered,'[^;]+',1,level) as triggered 

      from  t 

      connect by  id_tr = prior id_tr 
         and level <= regexp_count(triggered,';')+1 
         and prior sys_guid() is not null 
      ) t 

group by triggered 
; 
+0

Проверьте это. –

+0

Есть ли причина использовать sys_guid()? –

+0

@TymurGubayev - Он предотвращает «ORA-01436: цикл CONNECT BY в пользовательских данных» –

1
with x as (
    select listagg(Triggered, ';') within group (order by Id_TR) str from table 
) 
select regexp_substr(str,'[^;]+',1,level) element, count(*) 
    from x 
    connect by level <= length(regexp_replace(str,'[^;]+')) + 1 
    group by regexp_substr(str,'[^;]+',1,level); 

Первый сцепить все значения triggered в один список с помощью listagg затем разобрать его и сделать group by.

Другие методы списка синтаксического анализа вы можете найти here или here

+1

Нет причин объединять все, просто для де-конкатенации позже. Гораздо эффективнее разделить каждую строку отдельно. – mathguy

+0

Да! Когда я конкатенирую, он отправляет мне сообщение об ошибке ORA-01489: результат конкатенации строк слишком длинный. – Zombraz

+0

Похоже, мне нужно изменить тип данных на CLOB, так как Varchar2 очень ограничен. Я читал об использовании xmlagg, собираюсь дать ему попробовать ... – Zombraz

Смежные вопросы