Почему нельзя использовать так? 
	   
	     | 
   
 
	
		| Предыдущая тема :: Следующая тема   | 
	 
	
	
		| Автор | 
		Сообщение | 
	 
	
		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)$') | 	  
 
 
По себе, так я не вижу разницы в выборе инструментов, главное чтобы работало быстро и качественно. А про "китайский код", я имел ввиду, что читаемость кода достигается граммотными комментариями в сложных местах, а не выбором/копированием набитых шаблонов, которые увеличивают время обработки за счет "универсальности" и, возможно, стабильности, зато легко исправляемы какими-либо параметрами. Но каждый выбирает свой путь - я лишь предложил решение и высказал мнение    | 
			 
		  | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
	 
	    
	   | 
	
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
  | 
   
 
		 |