Oracle SQL: синтаксический анализ сумм транзакций из строкового столбца с разделителями полей - PullRequest
0 голосов
/ 09 февраля 2019

У меня есть два столбца в таблице Oracle SQL, в которых много важной информации о транзакциях хранится не так просто, чтобы их можно было найти.Набор данных имеет два столбца: trxn_a и trxn_b.

trxn_a:

2019-01-25 ~ денежный депозит ~ 5000 долларов ~ Джон Доу # 2019-01-26 ~ денежный депозит ~ 1000 долларов~ Джон Доу #

trxn_b:

2019-01-25 ~ денежный депозит ~ 3000 долларов ~ Джон Доу # 2019-01-25 ~ денежный депозит ~ 1500 долларов ~ ДжонDoe # 2019-01-26 ~ денежный депозит ~ 100 долларов ~ John Doe # 2019-01-26 ~ денежный депозит ~ 800 $ ~ John Doe # 2019-01-26 ~ денежный депозит ~ 100 $ ~ John Doe #

Как вы могли видеть, поля ограничены ~, а записи - #.Может быть любое количество транзакций (например, любое число # в ячейке).

Перечисленные выше данные - это всего лишь одна запись данных в двух столбцах (то есть две ячейки).

Моя цель - превратить данные в несколько строк, каждая строка будет агрегировать sum(trxn_amount) по дате.Пожалуйста, посмотрите желаемый результат ниже:

 date, trxn_amt_a, trxn_amt_b
 2019-01-25, 5000, 4500
 2019-01-26, 1000, 1000

Я пробовал функции INSTR и SUBSTR, но это не очень эффективно для обработки изменений в этой структуре данных.Кроме того, я не уверен, как:

  1. проанализировать даты, сумма транзакции
  2. агрегированных сумм по дате и
  3. , а затем разбить ячейки на разные строки

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Это сложный вопрос.Вот пошаговое описание того, как я поступил.


Первая часть состоит в разбиении каждого значения на строки с использованием разделителя #.Для этого мы используем REGEXP_SUBSTR() вместе с CONNECT BY для генерации рекурсии.

select trim(regexp_substr(trxn_a,'[^#]+', 1, level) ) trxn_a, level
from mytable
connect by regexp_substr(trxn_a, '[^#]+', 1, level) is not null

Затем нам нужно разобрать каждое результирующее значение в столбцы .Это можно сделать просто с помощью серии REGEXP_SUBSTR().Особое внимание следует уделить столбцу, который содержит значения суммы, которые содержат нецифровые символы ('$5,000'): необходимо удалить недопустимые символы, чтобы впоследствии значение можно было рассматривать как число.

Примечание: для вашей цели вам не нужно восстанавливать все 4 столбца из значения (достаточно указать дату и сумму);Я показываю все столбцы на случай, если вам когда-нибудь понадобится доступ к другому.

select
    'ta' src,
    regexp_substr(trxn_a,'[^~]+', 1, 1) tdate,
    regexp_substr(trxn_a,'[^~]+', 1, 2) ttype,
    replace(regexp_substr(trxn_a,'[^$~]+', 1, 3), ',', '') tamount,
    regexp_substr(trxn_a,'[^~]+', 1, 4) tuser
from (
    select trim(regexp_substr(trxn_a,'[^#]+', 1, level) ) trxn_a, level
    from mytable
    connect by regexp_substr(trxn_a, '[^#]+', 1, level) is not null
)

Каждый столбец в исходной таблице (trxn_a, trxn_b) должен обрабатываться отдельно, так как каждое значениегенерирует случайное количество записей.Результаты могут быть UNION ed, а затем внешний запрос выполняет условное агрегирование:

Окончательный запрос:

with t as (
    select
        'ta' src,
        regexp_substr(trxn_a,'[^~]+', 1, 1) tdate,
        regexp_substr(trxn_a,'[^~]+', 1, 2) ttype,
        replace(regexp_substr(trxn_a,'[^$~]+', 1, 3), ',', '') tamount,
        regexp_substr(trxn_a,'[^~]+', 1, 4) tuser
    from (
        select trim(regexp_substr(trxn_a,'[^#]+', 1, level) ) trxn_a, level
        from mytable
        connect by regexp_substr(trxn_a, '[^#]+', 1, level) is not null
    )
    union all
    select
        'tb' src,
        regexp_substr(trxn_b,'[^~]+', 1, 1) tdate,
        regexp_substr(trxn_b,'[^~]+', 1, 2) ttype,
        replace(regexp_substr(trxn_b,'[^$~]+', 1, 3), ',', '') tamount,
        regexp_substr(trxn_b,'[^~]+', 1, 4) tuser
    from (
        select trim(regexp_substr(trxn_b,'[^#]+', 1, level) ) trxn_b, level
        from mytable
        connect by regexp_substr(trxn_b, '[^#]+', 1, level) is not null
    )
)
select
    tdate, 
    SUM(DECODE(src, 'ta', tamount, 0)) trxn_amt_a,
    SUM(DECODE(src, 'tb', tamount, 0)) trxn_amt_b
from t
group by tdate;

С вашими тестовыми данными, эта демонстрация в БДСкрипка доходность:

TDATE       TRXN_AMT_A  TRXN_AMT_B
2019-01-25  5000        4500
2019-01-26  1000        1000
0 голосов
/ 09 февраля 2019

Используйте REGEXP_SUBSTR, чтобы разделить записи на #. Кроме того, я не вижу, как вы добавили еще один столбец, возможно, магию в операторе, которого у вас нет на входе.Просто Replace(the_below_string,'~cash deposit~',',')

      SELECT DISTINCT REGEXP_SUBSTR 
       ('2019-01-25~cash deposit~$5,000~John 
        Doe#2019-. 
      01-26~cash deposit~$1,000~John Doe#',
       '[^,#]+',1,LEVEL) as "Data" 
        FROM   Table
         CONNECT BY REGEXP_SUBSTR 
       ('2019-01-25~cash deposit~$5,000~John Doe#
         2019-01-26~cash deposit~$1,000~John Doe#
          ','[^,#]+',1,LEVEL) IS NOT NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...