Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема Запрос к многоуровневому справочнику (число прочтений - 2037 )
avgreen
Senior Member
****
Отсутствует



Сообщений: 254
Местоположение: Украина, Кривой Рог
Зарегистрирован: 20. Октября 2006
Пол: Мужской
Запрос к многоуровневому справочнику
02. Марта 2009 :: 07:14
Печать  
Возникла такая задача - сделать запрос к многоуровневому справочнику с поиском по наименованию. Т.е. типа найти элемент на третьем уровне по строке Наименование1\Наименование2\Наименование3
До сих пор это делалось рекурсией и Спр.НайтиПоНаименованию(). Мне показалось это несколько медленным .... особенно при частых вызовах. Попробовал написать через SQL - вышло в 2-3 раза медленнее Печаль Основное время занимала подготовка запроса - т.е. метод Открыть(). Ну, думаю, построю один раз параметризированный универсальный запрос и уже буду вызывать его, уже готовый. Но оказалось не так просто сделать универсальный запрос для любого количества уровней. Вот что примерно получилось для пяти уровней
Код
Выбрать все
select Константы1.ID as [ТекущийОбъект1 $Справочник.КонстантыПользователей],Константы2.ID as [ТекущийОбъект2 $Справочник.КонстантыПользователей],Константы3.ID as [ТекущийОбъект3 $Справочник.КонстантыПользователей],Константы4.ID as [ТекущийОбъект4 $Справочник.КонстантыПользователей],Константы5.ID as [ТекущийОбъект5 $Справочник.КонстантыПользователей]
 from  $Справочник.КонстантыПользователей as Константы1, $Справочник.КонстантыПользователей as Константы2, $Справочник.КонстантыПользователей as Константы3, $Справочник.КонстантыПользователей as Константы4, $Справочник.КонстантыПользователей as Константы5
 where  Константы1.Descr LIKE ?
 and  (( Константы2.Descr LIKE ?  and Константы2.ParentID = Константы1.ID and Константы2.IsMark = 0) or 2 > ? )
 and  (( Константы3.Descr LIKE ?  and Константы3.ParentID = Константы2.ID and Константы3.IsMark = 0) or 3 > ? )
 and  (( Константы4.Descr LIKE ?  and Константы4.ParentID = Константы3.ID and Константы4.IsMark = 0) or 4 > ? )
 and  (( Константы5.Descr LIKE ?  and Константы5.ParentID = Константы4.ID and Константы5.IsMark = 0) or 5 > ? ) 



В конце каждого условия 2 > ?, 3 > ? и т.д. - это попытка отключить условия неиспользуемых в данный момент уровней (т.е. на месте параметра макс. номер уровня). Для пяти уровней это естественно работает. Но если делаем запрос к примеру  по трем уровням справочника, последние две строки как-бы "отключаются", т.е. всегда TRUE: (4 > 3 и 5 > 3) ....... и блин в выборку попадает куча "повторов" от 4, 5 уровней. Ну т.е. практически весь справочник да еще два раза....
Может отсеять это как-то distinct или еще как - но знаний TSQL  не хватает Печаль
Или-же это вообще невозможно, типа как рекурсивный разбор с помощью RegExp?!

Единственная мысль как это обойти - подготовить 5 запросов, каждый для своего уровня, постоянно их хнаить и вызывать нужный .... но боюсь что мысль "не совсем умная"  Улыбка
  
Наверх
ICQ  
IP записан
 
ol
Senior Member
****
Отсутствует


1C++ rocks!

Сообщений: 272
Местоположение: Санкт-Петербург
Зарегистрирован: 24. Января 2009
Пол: Мужской
Re: Запрос к многоуровневому справочнику
Ответ #1 - 02. Марта 2009 :: 11:50
Печать  
а так:

Код
Выбрать все
Select
Спр.ID as [Константы0 $Справочник.КонстантыПользователей]
from $Справочник.КонстантыПользователей
left join $Справочник.КонстантыПользователей Константы1 on Константы1.ParentID=Константы0.ID
and Константы1.Descr Like ?
left join $Справочник.КонстантыПользователей Константы2 on Константы2.ParentID=Константы1.ID
and Константы2.Descr Like ?
	... и т.д.
where
Константы0.Descr Like ?
 



(или inner)?

  
Наверх
ICQ  
IP записан
 
avgreen
Senior Member
****
Отсутствует



Сообщений: 254
Местоположение: Украина, Кривой Рог
Зарегистрирован: 20. Октября 2006
Пол: Мужской
Re: Запрос к многоуровневому справочнику
Ответ #2 - 02. Марта 2009 :: 13:42
Печать  
Спасибо! Сейчас попробую - о результате отпишусь сюда...
  
Наверх
ICQ  
IP записан
 
Вадимко
God Member
*****
Отсутствует


Нам бы чего про ОдноЦэ...

Сообщений: 1048
Местоположение: Минск
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Запрос к многоуровневому справочнику
Ответ #3 - 02. Марта 2009 :: 22:33
Печать  
Может стоит завести реквизит Уровень и искать тупо в таблице?
Либо продублировать нужные служебные поля в своей таблице
  

Кампутер, кофе и сигареты - это очень плохо для моего здоровья...
Наверх
IP записан
 
avgreen
Senior Member
****
Отсутствует



Сообщений: 254
Местоположение: Украина, Кривой Рог
Зарегистрирован: 20. Октября 2006
Пол: Мужской
Re: Запрос к многоуровневому справочнику
Ответ #4 - 03. Марта 2009 :: 12:12
Печать  
ol писал(а) 02. Марта 2009 :: 11:50:
а так:
[skip]
(или inner)?

Огромное спасибо за мысль!  Помогло! Улыбка Заработало в следующем виде
Код
Выбрать все
select Константы1.ID as [ТекущийОбъект1 $Справочник.КонстантыПользователей],Константы2.ID as [ТекущийОбъект2 $Справочник.КонстантыПользователей],Константы3.ID as [ТекущийОбъект3 $Справочник.КонстантыПользователей],Константы4.ID as [ТекущийОбъект4 $Справочник.КонстантыПользователей],Константы5.ID as [ТекущийОбъект5 $Справочник.КонстантыПользователей]
 from $Справочник.КонстантыПользователей as Константы1
left join $Справочник.КонстантыПользователей as Константы2 on Константы2.ParentId=Константы1.ID
	and Константы2.Descr Like ?
left join $Справочник.КонстантыПользователей as Константы3 on Константы3.ParentId=Константы2.ID
	and Константы3.Descr Like ?
left join $Справочник.КонстантыПользователей as Константы4 on Константы4.ParentId=Константы3.ID
	and Константы4.Descr Like ?
left join $Справочник.КонстантыПользователей as Константы5 on Константы5.ParentId=Константы4.ID
	and Константы5.Descr Like ?  
where Константы1.Descr Like ?
and (Константы1.ID is not null or 1 > ?)
and (Константы2.ID is not null or 2 > ?)
and (Константы3.ID is not null or 3 > ?)
and (Константы4.ID is not null or 4 > ?)
and (Константы5.ID is not null or 5 > ?)
 



Именно "left join"! А то что не нужно (то что null) отсеиваем условием внизу. И это условие легко отключаемое. В 5 последних параметрах передаем текущий номер уровня, т.е. если Наименование1/Наименование2/Наименовени3 то туда подставиться "3" и два последних условий отключаются

И все-бы хорошо ..... но работает снова в 2 раза медленнее рекурсии с поиском по наименованию Печаль
Так что видать не судьба мне оптимизировать этот поиск - "все оптимизировано уже до нас". Улыбка   То-ли слишком сложный запрос получился, то-ли в индекс не попадаю.  Вобщем нужно рыть в другом месте
  
Наверх
ICQ  
IP записан
 
avgreen
Senior Member
****
Отсутствует



Сообщений: 254
Местоположение: Украина, Кривой Рог
Зарегистрирован: 20. Октября 2006
Пол: Мужской
Re: Запрос к многоуровневому справочнику
Ответ #5 - 03. Марта 2009 :: 12:13
Печать  
Вадимко писал(а) 02. Марта 2009 :: 22:33:
Может стоит завести реквизит Уровень и искать тупо в таблице?
Либо продублировать нужные служебные поля в своей таблице

Не совсем понял мысль Печаль
  
Наверх
ICQ  
IP записан
 
U_zer
Экс-Участник


Re: Запрос к многоуровневому справочнику
Ответ #6 - 03. Марта 2009 :: 12:33
Печать  
avgreen писал(а) 03. Марта 2009 :: 12:13:
Вадимко писал(а) 02. Марта 2009 :: 22:33:
Может стоит завести реквизит Уровень и искать тупо в таблице?
Либо продублировать нужные служебные поля в своей таблице

Не совсем понял мысль Печаль


Все прозрачно. Уровень - реквизит заведи, и включай его в условие запроса.
  
Наверх
 
IP записан
 
avgreen
Senior Member
****
Отсутствует



Сообщений: 254
Местоположение: Украина, Кривой Рог
Зарегистрирован: 20. Октября 2006
Пол: Мужской
Re: Запрос к многоуровневому справочнику
Ответ #7 - 03. Марта 2009 :: 12:59
Печать  
Не! Шо-то я видать не так померял! Сейчас пробую - вроди как соизмеримо и даже чуть быстрее
Скажем так - ускорения в 10 раз я не добился но все-же немного лучше. Нужно будет еще профилером подольше  побаловаться, а то 10-20 замеров на скорую руку могут и не показать истинную картину
  
Наверх
ICQ  
IP записан
 
avgreen
Senior Member
****
Отсутствует



Сообщений: 254
Местоположение: Украина, Кривой Рог
Зарегистрирован: 20. Октября 2006
Пол: Мужской
Re: Запрос к многоуровневому справочнику
Ответ #8 - 03. Марта 2009 :: 13:01
Печать  
Цитата:
avgreen писал(а) 03. Марта 2009 :: 12:13:
Вадимко писал(а) 02. Марта 2009 :: 22:33:
Может стоит завести реквизит Уровень и искать тупо в таблице?
Либо продублировать нужные служебные поля в своей таблице

Не совсем понял мысль Печаль


Все прозрачно. Уровень - реквизит заведи, и включай его в условие запроса.


Ну это-ж справочник 1С. Не хочется его корёжить - да и не нужно в свете последних событий Улыбка
Заработало и без доп реквизита а скорости он мне врядли прибавит
  
Наверх
ICQ  
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать