Предполагая, что это отдельная текстовая строка, в Oracle вы можете использовать несколько рекурсивных выражений подзапроса для разбиения строки на подстроки:
Установка Oracle :
CREATE TABLE table_name ( id, value ) AS
SELECT 1, '(1 JAN) INJECT 2ML (100MG) IV/IM AM THEN 0.5ML (25MG) 20 MIN LATER, THEN 2.5ML (125MG) PM'
|| '(SEP 20, 2018) INJECT 0.3ML (30MG) ON S1, 0.6ML (60MG) ON S2 AND 2ML(200MG) ON S3' FROM DUAL;
Запрос
WITH datelines ( id, value, dt, pos, lvl ) AS (
SELECT id,
value,
REGEXP_SUBSTR(
value,
'\((([0-2]?\d|3[01]) (JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC) ([0-2]?\d|3[01]), \d{4})\)',
1,
1,
NULL,
1
),
REGEXP_INSTR(
value,
'\((([0-2]?\d|3[01]) (JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC) ([0-2]?\d|3[01]), \d{4})\)',
1,
1
),
1
FROM table_name
UNION ALL
SELECT id,
value,
REGEXP_SUBSTR(
value,
'\((([0-2]?\d|3[01]) (JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC) ([0-2]?\d|3[01]), \d{4})\)',
1,
LVL + 1,
NULL,
1
),
REGEXP_INSTR(
value,
'\((([0-2]?\d|3[01]) (JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC) ([0-2]?\d|3[01]), \d{4})\)',
1,
LVL + 1
),
LVL + 1
FROM datelines
WHERE REGEXP_SUBSTR(
value,
'\((([0-2]?\d|3[01]) (JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC) ([0-2]?\d|3[01]), \d{4})\)',
1,
LVL + 1,
NULL,
1
) IS NOT NULL
),
actions ( id, dt, lvl, actions ) AS (
SELECT id,
dt,
lvl,
SUBSTR(
value,
pos + LENGTH( dt ) + 2,
LEAD( pos, 1, LENGTH( value ) + 1 ) OVER ( PARTITION BY id ORDER BY lvl ) - pos - LENGTH( dt ) - 2
)
FROM datelines
),
amounts ( id, dt, lvl, actions, amount, num_amounts, amount_lvl ) AS (
SELECT id,
dt,
lvl,
actions,
TO_NUMBER( REGEXP_SUBSTR( actions, '\((\d+)MG\)', 1, 1, NULL, 1 ) ),
REGEXP_COUNT( actions, '\((\d+)MG\)' ),
1
FROM actions
UNION ALL
SELECT id,
dt,
lvl,
actions,
TO_NUMBER( REGEXP_SUBSTR( actions, '\((\d+)MG\)', 1, amount_lvl + 1, NULL, 1 ) ),
num_amounts,
amount_lvl + 1
FROM amounts
WHERE amount_lvl < num_amounts
)
SELECT id,
dt,
SUM( amount ) AS total_amount
FROM amounts
GROUP BY id, dt, lvl;
выход
ID | DT | TOTAL_AMOUNT
-: | :----------- | -----------:
1 | SEP 20, 2018 | 290
1 | 1 JAN | 250
дБ <> скрипка здесь
Обновление
Если каждая строка находится в отдельной строке таблицы базы данных, то:
Установка Oracle :
CREATE TABLE table_name ( id, value ) AS
SELECT 1, '(1 JAN) INJECT 2ML (100MG) IV/IM AM THEN 0.5ML (25MG) 20 MIN LATER, THEN 2.5ML (125MG) PM' FROM DUAL UNION ALL
SELECT 2, '(SEP 20, 2018) INJECT 0.3ML (30MG) ON S1, 0.6ML (60MG) ON S2 AND 2ML(200MG) ON S3' FROM DUAL;
Запрос
WITH amounts ( id, value, dt, amount, amount_index, num_amounts ) AS (
SELECT id,
value,
REGEXP_SUBSTR( value, '\((.*?)\)', 1, 1, NULL, 1 ),
TO_NUMBER( REGEXP_SUBSTR( value, '\((\d+)MG\)', 1, 1, NULL, 1 ) ),
1,
REGEXP_COUNT( value, '\((\d+)MG\)' )
FROM table_name
UNION ALL
SELECT id,
value,
dt,
TO_NUMBER( REGEXP_SUBSTR( value, '\((\d+)MG\)', 1, amount_index + 1, NULL, 1 ) ),
amount_index + 1,
num_amounts
FROM amounts
WHERE amount_index < num_amounts
)
SELECT id,
MAX( dt ) AS dt,
SUM( amount ) AS total_amount
FROM amounts
GROUP BY id;
выход
ID | DT | TOTAL_AMOUNT
-: | :----------- | -----------:
1 | 1 JAN | 250
2 | SEP 20, 2018 | 290
дБ <> скрипка здесь