You can almost get there with REGEXP_REPLACE()
and a back reference:
REGEXP_REPLACE(REMARKS,'.*(PT LIAB|LIAB|LIABLE) (-?\d+[.]?\d+).*', '\2')
... but that passes a value without a matching pattern through untouched (so your third example would still get *SOC = 1178.00
. You can use a case expression and REGEXP_LIKE()
to avoid that:
with t (remarks) as (
select '*SOC 1369.00 - NCS 1239.46 = PT LIAB 129.54' from dual
union all select '*SOC 1369.00 - NCS 1239.46 = PT LIAB 140' from dual
union all select '*SOC = 1178.00' from dual
union all select '*SOC 1622.00 - NCS 209.74 = PT LIAB 1412.26 RECIPIENT AGE' from dual
union all select '*LINE #1 SOC 0.00 - NCS 22.77 = LIAB -22.77' from dual
union all select 'SOC MET AND CLEARED, SOC 2062-NCS 498.56=PT LIABLE 1563.44' from dual
)
SELECT REMARKS,
CASE WHEN REGEXP_LIKE(REMARKS, '.*(PT LIAB|LIAB|LIABLE) (-?\d+[.]?\d+).*')
THEN REGEXP_REPLACE(REMARKS,'.*(PT LIAB|LIAB|LIABLE) (-?\d+([.]\d+)?).*', '\2')
END as liability
from t;
REMARKS LIABILITY
---------------------------------------------------------- ----------
*SOC 1369.00 - NCS 1239.46 = PT LIAB 129.54 129.54
*SOC 1369.00 - NCS 1239.46 = PT LIAB 140 140
*SOC = 1178.00
*SOC 1622.00 - NCS 209.74 = PT LIAB 1412.26 RECIPIENT AGE 1412.26
*LINE #1 SOC 0.00 - NCS 22.77 = LIAB -22.77 -22.77
SOC MET AND CLEARED, SOC 2062-NCS 498.56=PT LIABLE 1563.44 1563.44
but that doesn't seem much better, and having the regex twice makes it even more expensive. (It could probably also still be simplified...). You could also use REGEXP_REPLACE()
instead of the two plain REPLACE()
calls:
REGEXP_REPLACE(
REGEXP_SUBSTR(REMARKS, '(PT LIAB|LIAB|LIABLE) (-?\d+([.]\d+)?)'),
'(PT LIAB|LIAB|LIABLE) ')
but again that's making it more expensive.