Van jouw commentaar tot het antwoord van @PrzemyslawKruglej
Het belangrijkste probleem is de interne zoekopdracht met
connect by
, het genereert een verbazingwekkende hoeveelheid rijen
Het aantal gegenereerde rijen kan worden verminderd met de volgende aanpak:
/* test table populated with sample data from your question */
SQL> create table t1(str) as(
2 select 'a;b;c' from dual union all
3 select 'b;c;d' from dual union all
4 select 'a;c;d' from dual
5 );
Table created
-- number of rows generated will solely depend on the most longest
-- string.
-- If (say) the longest string contains 3 words (wont count separator `;`)
-- and we have 100 rows in our table, then we will end up with 300 rows
-- for further processing , no more.
with occurrence(ocr) as(
select level
from ( select max(regexp_count(str, '[^;]+')) as mx_t
from t1 ) t
connect by level <= mx_t
)
select count(regexp_substr(t1.str, '[^;]+', 1, o.ocr)) as generated_for_3_rows
from t1
cross join occurrence o;
Resultaat:Voor drie rijen waarvan de langste uit drie woorden bestaat, genereren we 9 rijen :
GENERATED_FOR_3_ROWS
--------------------
9
Laatste vraag:
with occurrence(ocr) as(
select level
from ( select max(regexp_count(str, '[^;]+')) as mx_t
from t1 ) t
connect by level <= mx_t
)
select res
, count(res) as cnt
from (select regexp_substr(t1.str, '[^;]+', 1, o.ocr) as res
from t1
cross join occurrence o)
where res is not null
group by res
order by res;
Resultaat:
RES CNT
----- ----------
a 2
b 2
c 3
d 2
SQLFIddle-demo
Lees meer over regexp_count()(11g en hoger) en regexp_substr() reguliere expressiefuncties.
Opmerking: Reguliere expressiefuncties zijn relatief duur om te berekenen, en als het gaat om het verwerken van een zeer grote hoeveelheid gegevens, kan het de moeite waard zijn om over te schakelen naar een gewone PL/SQL. Hier is een voorbeeld.