2014-01-22 5 views
3

я наткнулся ниже сценарий,поиск конкретных символов в строке - Oracle

У меня есть имя столбца Broker_name немногие значения в нем являются 'tpt Broker','Mark iii', 'Davidtpt'

Окончательный выход для этих значений должны быть 'TPT Broker', 'Mark III','Davidtpt' в основном мне нужно CAPS несколько предварительно определенное значение в виде строки Say TPT, который поставляется с конечными пробелами, латинские буквы и т.д ..

так я создал таблицу поиска, которая имеет

Column1 Column2 
tpt  TPT 
iii  III 

не могли бы вы сообщить мне, как я могу проверить, присутствует ли в строке строка символов, а затем выполнить поиск по таблице. основываясь на этом?

+0

Интересный вызов. Я бы перекрестно присоединился к таблице поиска и использовал пользовательскую функцию агрегата для выполнения замены. Немного громоздко, может быть, кто-то придумает что-то умнее ... –

+0

Строго говоря, вы сломали 1NF. Я бы рассмотрел способы нормализации базы данных (разделить поле на атомарные составляющие). После этого ваша задача должна быть достижима довольно простым JOIN. –

ответ

0

Это немного сложно, так как оно должно быть нечувствительным к регистру (для таких вещей, как iIi или tpT). Обычно вы просто используете UPPER(), но хотите сохранить регистр остальных столбцов. Он также должен заменить МНОГО разных «неправильных» букв. И, наконец, вы не хотите, чтобы что-то вроде xxxtpt было подобрано, что сложно, если вы не можете идти пробелами (так как это может быть в начале или в конце). Я не уверен, какова ваша конечная цель. Я могу думать о двух:

  1. Вы просто хотите, чтобы запрос правильно отформатировал результаты.
  2. Вы хотите обновить любые значения, содержащие это.

В любом случае, это самое простое решение, которое я могу придумать (хотя и исправно). Вам придется учитывать все неправильные комбинации комбинаций (например: tpt, tpT, tPt, tPT, Tpt, TPt). Это немного перебор, но из-за недостатка времени и простоты (особенно если это всего несколько случаев), это будет работать:

Код:

Select 
Trim(
    Replace(
    Replace(
    Replace(
    Replace(
    Replace(
    --note the ' ' are added so we can search for a isolated instance of 
    --' tpt ' at the beginning or end of lines, as well as inbetween 
    -- these space get Trim()'d at in the end of processing everything. 
    Replace(' ' || test_t.text || ' ', ' tpt ', ' TPT ') 
            , ' tpT ', ' TPT ') 
            , ' tPt ', ' TPT ') 
            --etc... 
            , ' iii ', ' III ') 
            --etc... 
            , ' Iii ', ' III ') 
            , ' IIi ', ' III ') 
) 
as text 

--poor man's way of creating test tables 
From 
(
    Select 'tpt Broker' as text From dual UNION ALL 
    Select 'Mark iii' as text From dual UNION ALL 
    Select 'Davidtpt' as text From dual 
) test_t 

Результаты:

TPT Broker 
Mark III 
Davidtpt 

Это в значительной степени путь бедного человека. Я уверен, что есть более эффективные решения, если это долгосрочная проблема, но если ваши данные очищаются, это может сработать. Вы также можете попробовать использовать REGEXP_REPLACE или комбо INSTR. Если я подумаю о чем-то лучше, я обновлю этот пост.

EDIT:

Ой, я знал, что должен быть лучший способ. Использование REGEXP_REPLACE упрощает это. Я не смог заставить запрос «нечувствительный к регистру» работать (возможно, что-то не замечал).То же методика, но вот фактическое приличное решение:

Select 
    Trim(
     REGEXP_REPLACE(
     REGEXP_REPLACE(
      ' ' || text || ' ' , ' [tT][pP][tT] ', ' TPT ') 
           , ' [iI][iI][iI] ', ' III ') 
     ) as text 
From 
(
    Select 'tPt Broker' as text From dual UNION ALL 
    Select 'Mark iii' as text From dual UNION ALL 
    Select 'Davidtpt' as text From dual 
) test_t 
1

Наконец мне удалось справиться с ней с небольшой помощью пункта MODEL:

SELECT id, broker_name FROM (
    SELECT id, broker_name, rn, val, replacement 
    FROM brokers CROSS JOIN (SELECT rownum AS rn, val, replacement FROM lookup) 
    MODEL 
    PARTITION BY (id) 
    DIMENSION BY (rn) 
    MEASURES (val, replacement, broker_name) 
    RULES (
     broker_name[ANY] = regexp_replace(nvl(broker_name[CV()-1], broker_name[CV()]), 
             '(^|.*\W)' || val[CV()] || '(\W.*|$)', 
             '\1' || replacement[CV()] || '\2') 
    ) 
) 
WHERE rn = (SELECT count(*) FROM lookup) 
ORDER BY id, broker_name; 

В основном это делает следующее:

  1. Цифры в таблице поиска
  2. Выполняет перекрестное соединение между брокерами и поиском
  3. Для каждого брокера он выполняет итерацию по значениям поиска и делает замену (несколько странное регулярное выражение гарантирует замену только целых слов)
  4. Наконец, он берет окончательную строку только для каждого брокера, который содержит значение после всех замен были сделаны

Вот SQL Fiddle.

+0

Hello Kombajin, , когда я пытался использовать эти данные «Mark iii/tpt», он не работал. Fiddle here: - http://sqlfiddle.com/#!4/586f0/1 – Ragav

+0

Это из-за '/', и я использовал просто пространство (\ s) в качестве разделителя слов. Но мы также можем использовать любые не-буквенно-цифровые (\ W), проверить обновленный запрос (также скрипку здесь: http://sqlfiddle.com/#!4/586f0/4) –

+0

Процесс, кажется, работает для Long время. Также нам нужно сделать аналогичный поиск в другом столбце, можем ли мы объединить это в прикрепленный запрос? Рассмотрение 30 000 записей в исходной таблице и 8 строк в таблице поиска. Я думаю, что этот процесс может съесть время. есть ли другие варианты? как использование курсора. – Ragav

Смежные вопросы