2016-05-23 3 views
0

У нас есть таблица структуры.Oracle регулярное выражение для буквенно-цифровой проверки

 
From To Output 
A001 A555 "A" 
A556 A999 "B" 
AA01 AA55 "C" 
AA56 AA99 "D" 
B001 B555 "C" 

Если мое входное значение, если оно больше столбца From и меньше, чем столбец To, возвращает этот вывод. Например. Если я получил A222, верните вывод как «A». Если я получил AA22, верните вывод как «C».

В настоящее время я обрабатываю это на Java, но хотел бы проверить, могу ли я написать запрос Oracle (используя Regex) для получения выше вывода.

Благодаря SacH

+0

Что вы входное значение? Действительно непонятно, как АА становится «С» ... – Ben

+0

Каков диапазон букв? –

+0

Предположим, что я получил Input как A123, поэтому это значение больше A001 и меньше A555, поэтому запрос должен возвращать «A» из столбца вывода. Если I Received Input as AA12, то это значение больше AA01 и меньше AA99, поэтому запрос должен возвращать «A». Запрос сначала должен проверить исходные алфавиты, а затем сравнить числа для этой строки. Надеюсь, я здесь ясен. – sach

ответ

0

Вы должны извлечь VARCHAR и числовое значение из столбцов и входного значения и сравнить его друг другу

with tabl("FROM","TO",Output) as (
select 'A001','A555','A' from dual union all 
select 'A556','A999','B' from dual union all 
select 'AA01','AA55','C' from dual union all 
select 'AA56','AA99','D' from dual union all 
select 'B001','B555','C' from dual) 
select * from tabl 
where to_number(regexp_substr('AA22','[0-9]+')) between to_number(regexp_substr("FROM",'[0-9]+')) and to_number(regexp_substr("TO",'[0-9]+')) 
and regexp_substr('AA22','[^0-9]+') = regexp_substr("FROM",'[^0-9]+') 
1

Создать таблицу с соответствующими (виртуальных) столбцов и индексов:

Настройка

Oracle:

CREATE TABLE table_name (
    "from"  VARCHAR2(10) UNIQUE, 
    "to"   VARCHAR2(10) UNIQUE, 
    output  CHAR(1)  NOT NULL, 
    prefix  VARCHAR2(9) GENERATED ALWAYS AS (
           CAST(
           REGEXP_SUBSTR("from", '^\D+') 
           AS VARCHAR2(9) 
          ) 
          ) VIRTUAL, 
    from_postfix NUMBER(9) GENERATED ALWAYS AS (
          TO_NUMBER(REGEXP_SUBSTR("from", '\d+$')) 
          ) VIRTUAL, 
    to_postfix NUMBER(9) GENERATED ALWAYS AS (
           TO_NUMBER(REGEXP_SUBSTR("to", '\d+$')) 
          ) VIRTUAL, 
    CONSTRAINT table_name__from_to__u PRIMARY KEY (
    prefix, from_postfix, to_postfix 
), 
    CONSTRAINT table_name__f_t_prefix__chk CHECK (
    REGEXP_SUBSTR("from", '\^\D+') = REGEXP_SUBSTR("to", '\^\D+') 
) 
); 

INSERT INTO table_name ("from", "to", output) 
SELECT 'A001', 'A555', 'A' FROM DUAL UNION ALL 
SELECT 'A556', 'A999', 'B' FROM DUAL UNION ALL 
SELECT 'AA01', 'AA55', 'C' FROM DUAL UNION ALL 
SELECT 'AA56', 'AA99', 'D' FROM DUAL UNION ALL 
SELECT 'B001', 'B555', 'C' FROM DUAL; 

COMMIT; 

Запрос:

Тогда ваш запрос может использовать индекс и не нужно делать полное сканирование таблицы:

SELECT output 
FROM table_name 
WHERE REGEXP_SUBSTR(:input, '^\D+') = prefix 
AND TO_NUMBER(REGEXP_SUBSTR(:input, '\d+$')) 
     BETWEEN from_postfix 
     AND  to_postfix; 

Выход:

Если переменная input связывают это AA22 то результат:

OUTPUT 
------ 
C 

Explain Plan:

PLAN_TABLE_OUTPUT 
------------------------------------------- 
Plan hash value: 2408507965 
------------------------------------------------------------------------------------------------------ 
| Id | Operation     | Name     | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------------------------ 
| 0 | SELECT STATEMENT   |      |  1 | 35 |  2 (0)| 00:00:01 | 
| 1 | TABLE ACCESS BY INDEX ROWID| TABLE_NAME    |  1 | 35 |  2 (0)| 00:00:01 | 
|* 2 | INDEX RANGE SCAN   | TABLE_NAME__FROM_TO__U |  1 |  |  2 (0)| 00:00:01 | 
------------------------------------------------------------------------------------------------------ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 
     2 - access("PREFIX"= REGEXP_SUBSTR (:INPUT,'^\D+') AND "TO_POSTFIX">=TO_NUMBER(
       REGEXP_SUBSTR (:INPUT,'\d+$')) AND "FROM_POSTFIX"<=TO_NUMBER(REGEXP_SUBSTR (:INPUT,'\d+$'))) 
     filter("TO_POSTFIX">=TO_NUMBER(REGEXP_SUBSTR (:INPUT,'\d+$'))) 
+0

Это решение сработало для меня. Большое спасибо. – sach