Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Oracle > альтернатива LIKE (что посаветуете)


Автор: DimW 28.6.2010, 13:00
всем привет.

описание ситуации:

есть таблица с полем text varchar2(2000), в котором хранится информация о проводимых закупках той или иной продукции:

Код

create table reglike
(text varchar2(2000))
/

insert into reglike
values('Поставка рыбы детский оздоровительный лагерь')
/
insert into reglike
values('Продукты питания(рыба,)')
/
insert into reglike
values('Проведение запроса котировок для субъектов малого предпринимательства на поставку рыбы')
/
insert into reglike
values('Закупка рыбной продукции')
/
insert into reglike
values('Поставка колбасных изделий, рыбы, рыбных полуфабрикатов и рыбных консервов для санатория-профилактория')
/
insert into reglike
values('Поставка мороженой рыбы')
/


задача - из всего разнообразия закупок, выбрать для клиента закупки по его тематике по словосочетаниям.
словосочитания хранятся в справочнике.
Код

select * 
  from reglike rl
 where 1 = 1 -- некие дополнительные ограничения 
   -- динамическая часть
   and (upper(rl.text) like upper('%поставк%рыб%') or
        upper(rl.text) like upper('%продукт%рыб%') or
        upper(rl.text) like upper('%закупк%рыб%'))
     
   and (upper(rl.text) not like upper('%морожен%') and
        upper(rl.text) not like upper('%полуфабрик%')) 


запрос выбирает закупки рыбной продукции и исключает замороженную рыбу и полуфабрикаты.
в результат устраивает, но хотелось бы избавиться от динамической части с LIKE и NOT LIKE
что посоветуете?

ЗЫ. использовать OracleText нет возможности т.к. Oracle Standart Edition One

Автор: Zloxa 29.6.2010, 09:57
Цитата(DimW @  28.6.2010,  13:00 Найти цитируемый пост)
збавиться от динамической части с LIKE и NOT LIKE

регекспом?
Код

select * 
from reglike
where regexp_like(upper(text),upper('(поставк.*рыб)|(продукт.*рыб)|(закупк.*рыб)'),'i')
   and not regexp_like(upper(text),upper('(морожен)|(полуфабрик)'),'i')

Автор: DimW 29.6.2010, 11:08
догадывался что regexp поможет, но выражение родить не мог, спасибо!

Zloxa, из твоего опыта, траблы с производительностью при использовании regexp были? 
И интересуют все подводные камни.

еще вопрос, мне не всегда требуется применять словосочетания для подбора заявок, некоторых интересуют все заказы.

в случае с regexp_like  понятно передал * и выбирается все:
Код

regexp_like(upper(text),upper('*'),'i')


а как быть в случае с not regexp_like?

быть может возможно соответствие и отрицание построить одним выражением?
ну или какое выражение применить для not regexp_like что бы отрицание не применялось?

Добавлено через 9 минут и 35 секунд
странно, заявленная опция 'i' - Case insensitive matching не работает?
или работает не так как подумал?  smile 

Автор: DimW 29.6.2010, 11:26
Цитата(DimW @  29.6.2010,  11:08 Найти цитируемый пост)
интересуют все подводные камни.

а вот и камушки:
Код

delete from reglike
/        

insert into reglike
values('Поставка '|| chr(10) ||'рыбы детский оздоровительный лагерь')
/
insert into reglike
values('Продукты '|| chr(10) ||'питания(рыба,)')
/
insert into reglike
values('Проведение запроса котировок для субъектов малого предпринимательства на поставку рыбы')
/
insert into reglike
values('Закупка '|| chr(10) ||'рыбной продукции')
/
insert into reglike
values('Поставка колбасных изделий, рыбы, рыбных полуфабрикатов и рыбных консервов для санатория-профилактория')
/
insert into reglike
values('Поставка мороженой рыбы')
/

Код

SQL> 
SQL> select *
  2    from reglike rl
  3   where 1 = 1 -- некие дополнительные ограничения
  4     -- динамическая часть
  5     and (upper(rl.text) like upper('%поставк%рыб%') or
  6          upper(rl.text) like upper('%продукт%рыб%') or
  7          upper(rl.text) like upper('%закупк%рыб%'))
  8     and (upper(rl.text) not like upper('%морожен%') and
  9          upper(rl.text) not like upper('%полуфабрик%'))
 10  /
 
TEXT
--------------------------------------------------------------------------------
Поставка
рыбы детский оздоровительный лагерь
 
Продукты
питания(рыба,)
 
Проведение запроса котировок для субъектов малого предпринимательства на поставк
Закупка
рыбной продукции
 
SQL> 
SQL> select *
  2  from reglike
  3  where regexp_like(upper(text),upper('(поставк.*рыб)|(продукт.*рыб)|(закупк.*рыб)'),'i')
  4     and not regexp_like(upper(text),upper('(морожен.*рыб)|(полуфабрик.*рыб)'),'i')
  5  /
 
TEXT
--------------------------------------------------------------------------------
Проведение запроса котировок для субъектов малого предпринимательства на поставк
 
SQL> 


признак конца строки(chr(10)) не хавает, как с этим быть? 

Автор: Zloxa 29.6.2010, 11:31
Цитата(DimW @  29.6.2010,  11:08 Найти цитируемый пост)
как быть в случае с not regexp_like?

'^$' вроде как должен означать паттерн строки не имеющей ни одного символа(^-начало строки, $- конец), что в оракле не возможно, потмму всегда, по идее, должно фолсить.
Цитата(DimW @  29.6.2010,  11:08 Найти цитируемый пост)
из твоего опыта, траблы с производительностью при использовании regexp были? 

regexpы в продуктиве не использовал, но особых траблов с производительностью не неблюдал. Работают конечно определенно дольше лайка исравнения, вопрос с какого момента "дольше" считать проблемой ;)
Цитата(DimW @  29.6.2010,  11:08 Найти цитируемый пост)
И интересуют все подводные камни.

Всех никто не знает. Но они есть.
Не всегда ораклиный регексп работает так как написано во всяких букварях по регекспу. Некоторые паттерны не работают.
Из тех, которые я знаю точно- '.'(любой символ) не работает в 10,2,0,1

Автор: DimW 29.6.2010, 11:51
Цитата(Zloxa @  29.6.2010,  11:31 Найти цитируемый пост)
'^$' вроде как должен означать паттерн строки не имеющей ни одного символа

спасибо помогло smile

Цитата(Zloxa @  29.6.2010,  11:31 Найти цитируемый пост)
вопрос с какого момента "дольше" считать проблемой ;)

у меня для 2000 клиентов динамический лайк хавает едро полностью и формирование данных для всех клиентов занимает примерно 4 часа - ВОТ ЭТО ПРОБЛЕМА!  smile, думаю фулскан в данном случае менее вреден по сравнению с динамическим SQL.

а по поводу 
Цитата(DimW @  29.6.2010,  11:26 Найти цитируемый пост)
признак конца строки(chr(10)) не хавает, как с этим быть?  

есть что сказать?

Автор: Zloxa 29.6.2010, 12:03
Цитата(DimW @  29.6.2010,  11:51 Найти цитируемый пост)
а по поводу 
Цитата(DimW @  29.6.2010,  11:26 )
признак конца строки(chr(10)) не хавает, как с этим быть?  

Не заметил. Ты опубликовал второй пост, пока я тебе отвечал на первый.

Код

select *
  from reglike
  where regexp_like(upper(text),upper('(поставк.*рыб)|(продукт.*рыб)|(закупк.*рыб)'),'in')
     and not regexp_like(upper(text),upper('(морожен.*рыб)|(полуфабрик.*рыб)'),'in')

эт не камни, это фича.
а вот то что i не работает с кирилицей - видать камни.


Автор: DimW 29.6.2010, 12:10
Цитата(Zloxa @  29.6.2010,  12:03 Найти цитируемый пост)
эт не камни, это фича.
а вот то что i не работает с кирилицей - видать камни.


понятно, вечером погоняю, посмотрю и в продуктив smile
спасибо, как всегда исчерпывающий ответ!  smile 

Автор: Zloxa 29.6.2010, 12:12
кстати, попробуй на 11й c i и без upper
мне интересно - пофиксили?

Автор: DimW 29.6.2010, 12:16
Цитата(Zloxa @  29.6.2010,  12:12 Найти цитируемый пост)
попробуй на 11й c i и без upper


вечером попробую, о результатах отпишусь.

Автор: DimW 29.6.2010, 19:41
Цитата(Zloxa @  29.6.2010,  12:12 Найти цитируемый пост)
мне интересно - пофиксили? 


Цитата

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production 
PL/SQL Release 11.2.0.1.0 - Production 
CORE 11.2.0.1.0 Production 


да!  smile 

Автор: Zloxa 30.6.2010, 09:50
Цитата(Zloxa @  29.6.2010,  11:31 Найти цитируемый пост)
'^$' вроде как должен означать паттерн строки не имеющей ни одного символа(^-начало строки, $- конец), что в оракле не возможно, потмму всегда, по идее, должно фолсить.

пля
Код

SQL> select * from dual where regexp_like(chr(10),'^$','n');
 
DUMMY
-----
X
 

:((

Цитата(DimW @  29.6.2010,  11:08 Найти цитируемый пост)
как быть в случае с not regexp_like?

вопрос для меня открыт

Автор: DimW 30.6.2010, 12:10
Цитата(Zloxa @  30.6.2010,  09:50 Найти цитируемый пост)
вопрос для меня открыт

для меня не критично ибо:
Код

SQL> select * from dual where regexp_like(chr(10)||'value','^$','n')
  2  /
 
DUMMY
-----
SQL> select * from dual where regexp_like('value'||chr(10),'^$','n')
  2  /
 
DUMMY
-----
 
SQL> 


услуга без описания - все равно, что улица без названия...

Добавлено @ 12:17
кстати, погонял я вчера регэксп на своих нанных:

11g, ~300 000 строк -  лайку проиграл в ~4,5 раза.

10g, ~50 000 сток - лайку проиграл в ~85 раз.

то ли в 11g аптимизаровали регулярки, либо при увеличении объема данных лайк значительно теряет производительность.

но даже на 11g результат не утишительный - боюсь на продуктив ставить.
есть еще варианты как динамику в статику переделать при нынешней архитектуре? 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)