Преобразуйте String в Numeric, потянув слева от «:», а затем потянув вправо от «:» - PullRequest
0 голосов
/ 04 июля 2018

Text_value - столбец со строковыми значениями. Мне нужно искать ТОЛЬКО ':' и отделить левый от правого и преобразовать в числовое значение, чтобы я мог выполнить простой расчет. Если ':' не существует, я хочу вернуть нули. Я создаю представление в Oracle SQL Developer

Text_Value (Column)    
124  
7  
55:20  
73:00  
106:24  

Это мой код:

to_number(REGEXP_SUBSTR(b.text_value,'[^:]*',1,1)) AS Num,
to_number(REGEXP_SUBSTR(B.text_value,'[^:]*$'))  AS FRACTION2

Вот мои результаты:

results in Oracle

Я ожидаю, что text_values, которые не содержат ":", вернется как ноль. Это то, что я хотел бы увидеть.

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Вы можете избежать регулярных выражений и использовать вместо них instr и substr:

select text_value,
  to_number(case when instr(text_value, ':') > 0
    then substr(text_value, 1, instr(text_value, ':') - 1)
    else null end) as num,
  to_number(case when instr(text_value, ':') > 0
    then substr(text_value, instr(text_value, ':') + 1)
    else null end) as fraction2
from b;

Это делает больше вызовов отдельных функций, но они могут все же работать лучше, чем регулярные выражения, и вы можете переместить instr во встроенное представление, если хотите, так что вы не делаете это четыре раза (хотя оптимизатор может кэшировать результат в любом случае).

Демонстрация SQL Fiddle с использованием нескольких значений из вашего изображения и нескольких других вариантов, на которые вы не ссылались, и которые вы, возможно, захотите обработать по-другому.

Если они обрабатываются не так, как вы хотите, вы можете отрегулировать условия выражения регистра, например, для num меняется на > 1, а для fraction2 сравнивается с длиной строки - но это зависит от того, что вы хотите увидеть (и могут ли эти сценарии вообще существовать).

0 голосов
/ 04 июля 2018

Ты почти у цели. Вам просто нужно проверить, есть ли в строке :, прежде чем извлекать «секундную» часть строки:

SELECT TEXT_VALUE,
       TO_NUMBER(REGEXP_SUBSTR(text_value,'[^:]*',1,1)) AS MINUTES,
       CASE
         WHEN INSTR(TEXT_VALUE, ':') > 0 THEN TO_NUMBER(REGEXP_SUBSTR(text_value,'[^:]*$'))
         ELSE NULL
       END AS SECONDS
  FROM T;

TEXT_VALUE  MINUTES SECONDS
11          11      (null)
00:38       0       38
(null)      (null)  (null)
69:18       69      18
74:11       74      11
83:43       83      43
00:51       0       51
00:45       0       45
01:42       1       42
7           7       (null)
78:30       78      30
50          50      (null)
03:08       3       8
70:42       70      42
72:24       72      24
123         123     (null)
55:20       55      20

SQLFiddle здесь

EDIT

Вы можете избавиться от CASE, если вы измените второе регулярное выражение, чтобы включить, а не исключать двоеточие, а затем использовать SUBSTR, чтобы получить все символы, следующие за ::

SELECT TEXT_VALUE,
       TO_NUMBER(REGEXP_SUBSTR(text_value,'[^:]*',1,1)) AS MINUTES,
       SUBSTR(REGEXP_SUBSTR(text_value, ':.*$'), 2) AS SECONDS3
  FROM T;

Пересмотрено SQLFiddle здесь

0 голосов
/ 04 июля 2018

Вы можете проверить два числа, разделенных двоеточием, используя регулярное выражение ^(\d+):(\d+)$, например:

SQL Fiddle

Настройка схемы Oracle 11g R2 :

CREATE TABLE table_name ( text_value ) AS
SELECT '124' FROM DUAL UNION ALL
SELECT '7' FROM DUAL UNION ALL
SELECT '55:20' FROM DUAL UNION ALL
SELECT '73:00' FROM DUAL UNION ALL
SELECT '106:24' FROM DUAL;

Запрос 1 :

SELECT text_value,
       TO_NUMBER( REGEXP_SUBSTR( text_value, '^(\d+):(\d+)$', 1, 1, NULL, 1 ) ) AS num,
       TO_NUMBER( REGEXP_SUBSTR( text_value, '^(\d+):(\d+)$', 1, 1, NULL, 2 ) ) AS fraction2
FROM   table_name

Результаты

| TEXT_VALUE |    NUM | FRACTION2 |
|------------|--------|-----------|
|        124 | (null) |    (null) |
|          7 | (null) |    (null) |
|      55:20 |     55 |        20 |
|      73:00 |     73 |         0 |
|     106:24 |    106 |        24 |
...