Добавьте числа в строке в операторе SQL - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть ниже запрос, который я хотел бы изменить.

Я хочу суммировать все числа, встречающиеся в строке, с условием, что она объединяется с текстом ГБ или МБ.

Если он указан в ГБ, его сначала нужно преобразовать в MB. ( Это я сделал просто умножением на 1024 )

SELECT /*+ PARALLEL */ 
    'SOME TEXT 20GB+2GB+SOMETEXT' SOMETEXT, 
    CASE  
      WHEN REGEXP_SUBSTR('SOME TEXT 20GB+2GB+SOMETEXT','GB',1,1) = 'GB'
      THEN  1024*to_number(regexp_replace(REGEXP_SUBSTR('SOME TEXT 20GB+2GB+SOMETEXT','(\d+)GB',1,1), '[^0-9]', ''))
    ELSE to_number(regexp_replace(REGEXP_SUBSTR('SOME TEXT 20GB+2GB+SOMETEXT','(\d+)MB',1,1), '[^0-9]', ''))
   END TOTAL_MBs
FROM DUAL;

ТЕСТОВЫЕ СТРОКИ

TEXT TEXT_35MB+ MORETEXT
OTHERTEXT 480MB + 3MB AND_TEXT
SOMETEXT 7MB + 7NUMBER
TEXT 1GB AND SOME_TEXT
SOME TEXT 20GB+2GB+SOMETEXT

Вот где я застрял: Чтобы добавить числа, встречающиеся более одного раза, в один текст

Например: -

Для этого текста OTHERTEXT 480MB + 3MB AND_TEXT Я хочу, чтобы мой результат имел 483 в качестве TOTAL_MBS, а не 480

enter image description here

Ответы [ 3 ]

2 голосов
/ 06 февраля 2020

Вы можете использовать рекурсивное условие факторинга подзапроса:

  SELECT sometext,
         COALESCE(
           REGEXP_SUBSTR( sometext, '(\d+)([MG])B', 1, 1, NULL, 1 )
           * CASE REGEXP_SUBSTR( sometext, '(\d+)([MG])B', 1, 1, NULL, 2 )
             WHEN 'M' THEN 1
             WHEN 'G' THEN 1024
             END,
           0
         ),
         1,
         REGEXP_COUNT( sometext, '(\d+)([MG])B' )
  FROM   test_data
UNION ALL
  SELECT sometext,
         total_mb
         + REGEXP_SUBSTR( sometext, '(\d+)([MG])B', 1, i + 1, NULL, 1 )
         * CASE REGEXP_SUBSTR( sometext, '(\d+)([MG])B', 1, i + 1, NULL, 2 )
           WHEN 'M' THEN 1
           WHEN 'G' THEN 1024
           END,
         i + 1,
         num_terms
  FROM   terms
  WHERE  i < num_terms
)
SELECT sometext,
       total_mb
FROM   terms
WHERE  i >= num_terms;

, которое для тестовых данных:

CREATE TABLE test_data ( sometext ) AS
  SELECT 'SOME TEXT 20GB+2GB+SOMETEXT' FROM DUAL UNION ALL
  SELECT '1MB+1GB+10MB+10GB' FROM DUAL;

выводит:

SOMETEXT                    | TOTAL_MB
:-------------------------- | -------:
SOME TEXT 20GB+2GB+SOMETEXT |    22528
1MB+1GB+10MB+10GB           |    11275

дБ <> скрипка здесь

2 голосов
/ 06 февраля 2020

Думаю, вы ищете что-то вроде:

with da as (
              select 1 id, 'TEXT TEXT_35MB+ MORETEXT' tcase from dual
    union all select 2 id,'OTHERTEXT 480MB + 3MB AND_TEXT' tcase from dual
    union all select 3 id,'SOMETEXT 7MB + 7NUMBER' tcase from dual
    union all select 4 id,'TEXT 1GB AND SOME_TEXT' tcase from dual
    union all select 5 id,'SOME TEXT 20GB+2GB+SOMETEXT' tcase from dual
    union all select 6 id,'SOME TEXT 20MB+2GB+SOMETEXT' tcase from dual
    ),
split as( 
    select  id
         ,  tcase 
         ,  REGEXP_SUBSTR(tcase,'(\d+)(M|G)B',1,level) ot  
    from    da
    connect by REGEXP_SUBSTR(tcase,'(\d+)(M|G)B',1,level)is not null
    and     prior id = id
    and     PRIOR DBMS_RANDOM.VALUE IS NOT NULL)
select  id
      , tcase
      , sum( case when ot like '%GB%' then 1024 else 1 end * regexp_substr(ot,'\d+'))  v 
from    split 
group by id
        ,tcase
order by id;

Результат:

1   TEXT TEXT_35MB+ MORETEXT             35
2   OTHERTEXT 480MB + 3MB AND_TEXT      483
3   SOMETEXT 7MB + 7NUMBER                7
4   TEXT 1GB AND SOME_TEXT             1024
5   SOME TEXT 20GB+2GB+SOMETEXT       22528
6   SOME TEXT 20MB+2GB+SOMETEXT        2068
1 голос
/ 07 февраля 2020

ниже Я использовал таблицу представления / памяти, чтобы назначить функцию регулярного выражения для указанной строки c, и это сработало для меня

with tbl1 as (
              select  1 pd, ' 20GB+2GB sometext +7500 + 45sometext' string from dual 
        ),   
tbl2 as( 
    select  pd
         ,  string 
         ,  REGEXP_SUBSTR(string,'(\d+)(M|G)B',1,level) string2  
    from    tbl1
    connect by REGEXP_SUBSTR(string,'(\d+)(M|G)B',1,level)is not NULL
       and     prior pd = pd
    and     PRIOR DBMS_RANDOM.VALUE IS NOT NULL)
select  pd
      , string
      , sum( case when string2 like '%GB%' then 1024 end * regexp_substr(string2,'\d+'))  string3
from    tbl2 
group by pd
        ,string
order by pd; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...