Oracle REGEXPR_SUBSTR - PullRequest
       9

Oracle REGEXPR_SUBSTR

0 голосов
/ 17 ноября 2018

Я надеюсь, что кто-нибудь может дать мне хороший способ сделать это:

У меня есть строка:

annual_sales:79139,annual_ind:A,q4_sales:22543,q4_ind:A,q3_sales:19153,q3_ind:A,q2_sales:19289,q2_ind:A,q1_sales:18155,q1_ind:A

Строка всегда будет иметь одинаковые части. Всегда 10 разделов, разделенных запятыми. Каждые 2 пары идут вместе. Итак, вы видите это:

annual_sales:79139
annual_ind:A

q4_sales:22543
q4_ind:A

q3_sales:19153
q3_ind:A

q2_sales:19289
q2_ind:A

q1_sales:18155
q1_ind:A

Мне нужны обе пары для необходимой обработки.

Мне нужны annual_sales:79139 и annual_ind:A, чтобы обработать это.

Мне нужно и q4_sales:22543, и q4_ind:A, чтобы обработать это, и так далее

Я надеюсь, что как-то, возможно, с циклом и REGEXPR_SUBSTR, чтобы получить пары. Может быть, 5 раз, получи пары, которые мне нужны каждый раз?

Я могу сделать это очень неуклюже с SUBSTR & INSTR, но надеюсь, что REGEXPR может быть немного более чистым.

Итак, извлеките первые 2 пары, делайте то, что мне нужно. Получить вторые 2 пары, делать то, что нужно и т. Д.

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Вот решение для регулярных выражений, которое не требует жесткого кодирования меток. Подзапрос разбивает строку на каждую вторую запятую, затем основной запрос разбивает результирующую пару на два столбца.

with t23 as  (
  select  'annual_sales:79139,annual_ind:A,q4_sales:22543,q4_ind:A,q3_sales:19153,q3_ind:A,q2_sales:19289,q2_ind:A,q1_sales:18155,q1_ind:A' str
  from dual
 )
  , prs as (
  select regexp_substr(str, '([^,]+,[^,]+)', 1, level) as pr
  from t23
  connect by level <= 5 
  )
select substr(pr, 1, instr(pr, ',')-1) as sales
       , substr(pr, instr(pr, ',')+1) as ind
from prs
order by 1
;

Вывод выглядит так:

SALES               IND
------------------  -----------
annual_sales:79139  annual_ind:A
q1_sales:18155      q1_ind:A
q2_sales:19289      q2_ind:A
q3_sales:19153      q3_ind:A
q4_sales:22543      q4_ind:A

Если вы хотите иметь что-то, что готово для обработки, мы можем придумать:

with t23 as  (
  select  'annual_sales:79139,annual_ind:A,q4_sales:22543,q4_ind:A,q3_sales:19153,q3_ind:A,q2_sales:19289,q2_ind:A,q1_sales:18155,q1_ind:A' str
  from dual
 )
  , prs as (
  select regexp_substr(str, '([^,]+,[^,]+)', 1, level) as pr
  from t23
  connect by level <= 5 
  )
select substr(pr, 1, instr(pr, '_')-1) as label
       , ltrim(regexp_substr(pr, ':([0-9]+)'), ':') as sales
       , substr(pr, -1, 1) as ind
from prs
order by 1
; 

Дает вывод:

LABEL   SALES  IND
------  -----  ---
annual  79139  A
q1      18155  A
q2      19289  A
q3      19153  A
q4      22543  A

Кстати, этот вопрос иллюстрирует мой багбир. Этот вопрос необходим только потому, что входная строка плохо отформатирована. В контенте есть неявная структура, которая не выражена в структуре строки. Это 2018 год, почему мы до сих пор передаем данные вот так? У нас был XML на протяжении десятилетий, JSON с 2001 года. Нет оправдания.

Я согласен, что это более многословно, но насколько легче обрабатывать, насколько надежнее:

"report": {
    "annual" : {
       "sales" : 79139
       , "ind" : A
    }
    , "q1" : {
       "sales" : 18155
       , "ind" : A
    }
    , "q2" : {
       "sales" : 19289
       , "ind" : A
    }
    , "q3" : {
       "sales" : 19153
       , "ind" : A
    }
    , "q4" : {
       "sales" : 22543
       , "ind" : A
    }
}

Купите, вам не нужно использовать полный JSON. Даже это было бы заметным улучшением:

[annual_sales:79139,annual_ind:A],[q4_sales:22543,q4_ind:A],[q3_sales:19153,q3_ind:A],[q2_sales:19289,q2_ind:A],[q1_sales:18155,q1_ind:A]

По крайней мере, у нас есть надежная запись для связанных пар значений.

0 голосов
/ 17 ноября 2018

Я предлагаю использовать что-то вроде:

SELECT REGEXP_SUBSTR(SALES_STRING, '(annual_sales:)([^,]+)',1,1,NULL,2) AS ANNUAL_SALES,
       REGEXP_SUBSTR(SALES_STRING, '(annual_ind:)([^,]+)',1,1,NULL,2) AS ANNUAL_IND,
       REGEXP_SUBSTR(SALES_STRING, '(q1_sales:)([^,]+)',1,1,NULL,2) AS Q1_SALES,
       REGEXP_SUBSTR(SALES_STRING, '(q1_ind:)([^,]+)',1,1,NULL,2) AS Q1_IND,
       REGEXP_SUBSTR(SALES_STRING, '(q2_sales:)([^,]+)',1,1,NULL,2) AS Q2_SALES,
       REGEXP_SUBSTR(SALES_STRING, '(q2_ind:)([^,]+)',1,1,NULL,2) AS Q2_IND,
       REGEXP_SUBSTR(SALES_STRING, '(q3_sales:)([^,]+)',1,1,NULL,2) AS Q3_SALES,
       REGEXP_SUBSTR(SALES_STRING, '(q3_ind:)([^,]+)',1,1,NULL,2) AS Q3_IND,
       REGEXP_SUBSTR(SALES_STRING, '(q4_sales:)([^,]+)',1,1,NULL,2) AS Q4_SALES,
       REGEXP_SUBSTR(SALES_STRING, '(q4_ind:)([^,]+)',1,1,NULL,2) AS Q4_IND
  FROM YOUR_TABLE

, где YOUR_TABLE.SALES_STRING - это таблица и столбец, содержащий строку.Это даст результат, подобный следующему:

ANNUAL_SALES ANNUAL_IND Q1_SALES Q1_IND Q2_SALES Q2_IND Q3_SALES Q3_IND Q4_SALES  Q4_IND
79139        A          18155    A      19289    A      19153    A      22543     A

dbfiddle здесь

Удачи.

...