Почему нельзя использовать так?
|
Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
arkazar Участник со стажем
Вступление в Клуб: 27.09.2010
|
Пт Дек 21, 2012 14:39  Почему нельзя использовать так? |
|
Полезность: Нет оценки
|
Всем, Привет!
Подскажите, почему так работает:
where prop.[GROUP_PROP].[CODE] in ('NRD_CL_2171_CD','NRD_CL_2171_CB','NRD_CL_2171_P','NRD_CL_2171_CS','NRD_CL_2171_CBS','NRD_CL_2171_KF','NRD_CL_2171_VP','NRD_CL_RELATION')
А так нет? :
str_val string;
begin
str_val:=::[FP_TUNE].[LIB].get_str_value('NRD_CL_2171');
debug_pipe('str_val='||str_val,0);
for (select x(x.[GROUP_PROP].[CODE] oper_code) in Prop_arr
where x.[GROUP_PROP].[CODE] in (str_val)
)
loop |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Пт Дек 21, 2012 14:45   |
|
Полезность: Нет оценки
|
потому, что синтаксис.
in подразумевает последовательность аргументов.
если нужно пробежаться по сборной строке параметров, нужно что то вроде where instr(str_val,code ) > 0 |
|
 |
arkazar Участник со стажем
Вступление в Клуб: 27.09.2010
|
Пт Дек 21, 2012 15:14   |
|
Полезность: Нет оценки
|
Не совсем понял...
это куда надо? inst же выводит значениие позиции фразы.... |
|
 |
Volod Эксперт
Вступление в Клуб: 19.09.2007
|
Пт Дек 21, 2012 15:28   |
|
Полезность: Нет оценки
|
Используйте regexp_like |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Пт Дек 21, 2012 15:28   |
|
Полезность: Нет оценки
|
как то так
for (select x(x.[GROUP_PROP].[CODE] oper_code) in Prop_arr
where substr(str_val,x.[GROUP_PROP].[CODE] ) >0
loop
ну и для полного щастья обвесить trim, upper и nvl  |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Пт Дек 21, 2012 15:31   |
|
Полезность: Нет оценки
|
Volod пишет: | Используйте regexp_like |
Вы ещо аналитические функции Запросчику посоветуйте
8( ) |
|
 |
Volod Эксперт
Вступление в Клуб: 19.09.2007
|
Пт Дек 21, 2012 15:45   |
|
Полезность: Нет оценки
|
Шаблон несложный:
where regexp_like(prop.[GROUP_PROP].[code], '^(NRD_CL_2171_CD|NRD_CL_2171_CB|NRD_CL_2171_P|NRD_CL_2171_CS|NRD_CL_2171_CBS|NRD_CL_2171_KF|NRD_CL_2171_VP|NRD_CL_RELATION)') |
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Пн Дек 24, 2012 13:57   |
|
Полезность: Нет оценки
|
Volod пишет: | Шаблон несложный:
where regexp_like(prop.[GROUP_PROP].[ code ], '^(NRD_CL_2171_CD|NRD_CL_2171_CB|NRD_CL_2171_P|NRD_CL_2171_CS|NRD_CL_2171_CBS|NRD_CL_2171_KF|NRD_CL_2171_VP|NRD_CL_RELATION)') |
Если не считать того, что регулярные выражения тут нафик не нужны, а только кушают ресурсы...
Вы же на марсолёте на работу не летаете каждый день?
Код: |
declare
str_val varchar2(32767) := 'NRD_CL_2171_CD,NRD_CL_2171_CB,NRD_CL_2171_P,NRD_CL_2171_CS,NRD_CL_2171_CBS,NRD_CL_2171_KF,NRD_CL_2171_VP,NRD_CL_RELATION';
begin
for (select x(x.[GROUP_PROP].[ CODE ] oper_code) in Prop_arr
where instr( ',' || str_val || ','
,',' || x.[GROUP_PROP].[ code ] || ',' ) >0
loop
...
|
1. instr с null возвращает null. Если строка никогда не будет пустой, эту ветку можно не обрабатывать.
2. данный instr обрабатывает обе ситуации, когда строка приходит с начинающей запятой и завершающей запятой, или без них.
3. Разделитель, естественно, любой, в ЦФТ часто используют #
4. запрос с in использует индекс, запрос с instr может использовать индекс (но уже не в этом условии) - /дальше много буков об оптимизации/ это вопрос к оптимальности. Если результат запроса с in даёт < 5% таблицы, лучше in, если больше - instr, опять же instr даёт возможность использовать другие индексы, типа с collection_id, точнее не искушает оптимизатор Oracle сойти с нужного индекса. |
|
 |
Reddom Участник со стажем
Вступление в Клуб: 25.01.2013
|
Пт Янв 25, 2013 09:36   |
|
Полезность: Нет оценки
|
Так мне кажется будет быстрее (В pl+ переделывается в минуты, суть разбить строку на части и превратить в табличку, из которой работает выборка по IN):
Код: | select * from Z#MAIN_DOCUM where id in (
select
regexp_substr(str, '[^,]+', 1, level) as codes
from
(select '13209770,13209786,13209802,13207482' as "STR" from dual)
connect by level <= regexp_count(str, '[^,]+')); |
План выполнения:
Код: | SELECT STATEMENT, GOAL = ALL_ROWS Cost=4 Cardinality=1 Bytes=543
NESTED LOOPS
NESTED LOOPS Cost=4 Cardinality=1 Bytes=543
VIEW Object owner=SYS Object name=VW_NSO_1 Cost=3 Cardinality=1 Bytes=19
HASH UNIQUE Cost=3 Cardinality=1
CONNECT BY WITHOUT FILTERING (UNIQUE)
FAST DUAL Cost=2 Cardinality=1
INDEX UNIQUE SCAN Object owner=IBS Object name=PK_Z#MAIN_DOCUM_ID Cost=1 Cardinality=1
TABLE ACCESS BY INDEX ROWID Object owner=IBS Object name=Z#MAIN_DOCUM Cost=1 Cardinality=1 Bytes=524 |
|
|
 |
Random Эксперт
Вступление в Клуб: 27.06.2011
|
Пн Янв 28, 2013 16:22   |
|
Полезность: Нет оценки
|
Reddom пишет: | Так мне кажется будет быстрее (В pl+ переделывается в минуты, суть разбить строку на части и превратить в табличку, из которой работает выборка по IN):
Код: | select * from Z#MAIN_DOCUM where id in (
select
regexp_substr(str, '[^,]+', 1, level) as codes
from
(select '13209770,13209786,13209802,13207482' as "STR" from dual)
connect by level <= regexp_count(str, '[^,]+')); |
План выполнения:
Код: | SELECT STATEMENT, GOAL = ALL_ROWS Cost=4 Cardinality=1 Bytes=543
NESTED LOOPS
NESTED LOOPS Cost=4 Cardinality=1 Bytes=543
VIEW Object owner=SYS Object name=VW_NSO_1 Cost=3 Cardinality=1 Bytes=19
HASH UNIQUE Cost=3 Cardinality=1
CONNECT BY WITHOUT FILTERING (UNIQUE)
FAST DUAL Cost=2 Cardinality=1
INDEX UNIQUE SCAN Object owner=IBS Object name=PK_Z#MAIN_DOCUM_ID Cost=1 Cardinality=1
TABLE ACCESS BY INDEX ROWID Object owner=IBS Object name=Z#MAIN_DOCUM Cost=1 Cardinality=1 Bytes=524 |
|
Интересное решение. А не пробовали nested_varray применить? |
|
 |
devor Профи
Вступление в Клуб: 13.02.2012
|
Вт Янв 29, 2013 07:35   |
|
Полезность: 1
|
Применение сложных решений для простых задач сильно портит карму.
Сопровождающие такой код будут потом долго вспоминать разработчика ласковыми выражениями. |
|
 |
Reddom Участник со стажем
Вступление в Клуб: 25.01.2013
|
Чт Янв 31, 2013 14:25   |
|
Полезность: Нет оценки
|
Random пишет: | Интересное решение. А не пробовали nested_varray применить? |
К данному случаю, я считаю, что не имеет особого смысла:
Код: | VIEW Object owner=SYS Object name=VW_NSO_1 Cost=3 Cardinality=1 Bytes=19
HASH UNIQUE Cost=3 Cardinality=1
CONNECT BY WITHOUT FILTERING (UNIQUE)
FAST DUAL Cost=2 Cardinality=1 |
Видно, что создается псевдовьюха с кодами и стоимость её 3, чтения с диска нет и т.п.. Так что по стоимости в производительности выигрыша максимум cost = 1. Ну и как плюс приведенное решение можно использовать в чистом sql, например представлениях.
devor пишет: | Применение сложных решений для простых задач сильно портит карму.
Сопровождающие такой код будут потом долго вспоминать разработчика ласковыми выражениями. |
Качественно хороший и правильно оформленный с комментариями даже очень сложный код читается не хуже "китайского кода", где вместо sql предпочитают пользоваться многоразовым вызовом интерфейса, который, если прочитать код, все равно каждый раз производит чтение с таблицы sql запросом. И тут уже вопрос в производительности. Connect by level вполне освояем прочтением документации Oracle в течении 10-20 минут. Регулярные выражения чуть дольше, но выигрыш в производительности окупает в десятки раз потерянное время "сопровождающих" код. К приведенному мной примеру можно комментарием вставить:
Код: | /*разбиваем строку на id по запятым*/ |
|
|
 |
devor Профи
Вступление в Клуб: 13.02.2012
|
Чт Янв 31, 2013 15:44   |
|
Полезность: Нет оценки
|
Reddom пишет: |
devor пишет: | Применение сложных решений для простых задач сильно портит карму.
Сопровождающие такой код будут потом долго вспоминать разработчика ласковыми выражениями. |
Качественно хороший и правильно оформленный с комментариями даже очень сложный код читается не хуже "китайского кода", где вместо sql предпочитают пользоваться многоразовым вызовом интерфейса, который, если прочитать код, все равно каждый раз производит чтение с таблицы sql запросом. И тут уже вопрос в производительности. Connect by level вполне освояем прочтением документации Oracle в течении 10-20 минут. Регулярные выражения чуть дольше, но выигрыш в производительности окупает в десятки раз потерянное время "сопровождающих" код. К приведенному мной примеру можно комментарием вставить:
Код: | /*разбиваем строку на id по запятым*/ |
|
Зачем тут иерархические запросы и регулярные выражения, когда достаточно простого instr, что и было сразу предложено изначально?
Инструменты надо подбирать исходя из поставленной задачи - гвоздь можно забить шуруповертом, но неудобно.
А реплика про "Китайский код" с интерфейсами и вовсе непонятно в какую кассу. |
|
 |
devor Профи
Вступление в Клуб: 13.02.2012
|
Чт Янв 31, 2013 16:20   |
|
Полезность: Нет оценки
|
Надеюсь, понятно, что id имеет индекс, поэтому такой красивый план?
Он(план) будет совсем другим для поля без индекса, например, c_num_check |
|
 |
Reddom Участник со стажем
Вступление в Клуб: 25.01.2013
|
Пт Фев 01, 2013 08:18   |
|
Полезность: Нет оценки
|
devor пишет: | Надеюсь, понятно, что id имеет индекс, поэтому такой красивый план?
Он(план) будет совсем другим для поля без индекса, например, c_num_check |
Идея моего запроса и была в том, чтобы запрос встал на индекс. Если поле без индекса, то в полне подойдет вариант предложенный Volod, который по мне так более читабельный, чем с instr:
Volod пишет: | Шаблон несложный:
where regexp_like(prop.[GROUP_PROP].[code], '^(NRD_CL_2171_CD|NRD_CL_2171_CB|NRD_CL_2171_P|NRD_CL_2171_CS|NRD_CL_2171_CBS|NRD_CL_2171_KF|NRD_CL_2171_VP|NRD_CL_RELATION)$') |
По себе, так я не вижу разницы в выборе инструментов, главное чтобы работало быстро и качественно. А про "китайский код", я имел ввиду, что читаемость кода достигается граммотными комментариями в сложных местах, а не выбором/копированием набитых шаблонов, которые увеличивают время обработки за счет "универсальности" и, возможно, стабильности, зато легко исправляемы какими-либо параметрами. Но каждый выбирает свой путь - я лишь предложил решение и высказал мнение  |
|
 |
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|