Это не будет самым эффективным, но здесь я разбиваю его на более мелкие шаги. Может быть, поможет другой подход к проблеме. Я сомневаюсь, что вы захотите использовать это для больших наборов данных.
with testdata(id, bizname) as (
-- Base data
select 1, 'MI ROOFING LLC' from dual union all
select 2, 'LAKESHORE LLC NILES MI' from dual union all
select 3, 'MIDLAND WILLCOX' from dual
),
parsedata(id, ord, element) as (
-- Treat as a delimited string and parse elements into rows,
-- Initcap()'ing elements not in the "leave-alone" list.
select id, level as ord,
case
when regexp_substr(bizname, '(.*?)( |$)', 1, level, null, 1) in ('MI', 'LLC')
then regexp_substr(bizname, '(.*?)( |$)', 1, level, null, 1)
else
initcap(regexp_substr(bizname, '(.*?)( |$)', 1, level, null, 1))
end as element
from testdata
connect by regexp_substr(bizname, '(.*?)( |$)', 1, level) is not null
and prior id = id
and prior sys_guid() is not null
)
--select * from parsedata;
-- Put the rows back together.
SELECT ID, LISTAGG(element, ' ') WITHIN GROUP (ORDER BY ord) bizname
FROM parsedata
GROUP BY id
ORDER BY id;
>
ID BIZNAME
---------- -------------------------
1 MI Roofing LLC
2 Lakeshore LLC Niles MI
3 Midland Willcox
3 rows selected.