Переключение на Главную Страницу Страницы: [1]  ОтправитьПечать
Горячая тема (более 10 ответов) Прямой запрос и штатное средство (число прочтений - 4528 )
Kondarat
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 83
Зарегистрирован: 21. Декабря 2007
Прямой запрос и штатное средство
27. Марта 2008 :: 07:13
Печать  
Планируется перевод базы на SQL, вот и решил затестить.
Суть: есть такая конструкция, кторая выводит в ТЗ на форме остатки по текущему товару в разрезе подразделений:
     ТЗ_Наличие.УдалитьСтроки();
     Для Н=1 По СпПодр.РазмерСписка() Цикл
           Подр=СпПодр.ПолучитьЗначение(Н,);
           Кол=РегОТ.СводныйОстаток(Подр,ВыбНоменклатура,,"Количество");
           МинОстаток = ВыбНоменклатура.МинимальныйОстаток; 
           КонтрольМинОстатка = Подр.КонтрольМинОстатка;
           Разница = 0;
           Если (КонтрольМинОстатка = 1) И (МинОстаток <> 0) Тогда
                 Разница = Кол - МинОстаток;
           КонецЕсли;      
           Если Кол<>0 Тогда
                 ТЗ_Наличие.НоваяСтрока();
                 ТЗ_Наличие.Склад=Подр;
                 ТЗ_Наличие.Количество=Кол;
                 Если Разница < 0 Тогда
                       ТЗ_Наличие.Пикт = 35;
                 КонецЕсли;      
           КонецЕсли;
     КонецЦикла;

Пытаюсь этот код переложить на прямой запрос следующим образом:
     ТекстЗапроса = "
     |Select
     |    Номенклатура [Товар $Справочник.Номенклатура],
     |    Подразделение [Склад $Справочник.Подразделения], 
     |    КоличествоОстаток ОстатокТовара
     |FROM
     |    $РегистрОстатки.Склад(
     |      ,
     |      ,
     |      (Номенклатура = :ВыбНоменклатура) And Подразделение in (Select val from #ВыбСклад),
     |      (Подразделение, Номенклатура),
     |      Количество
     |      ) остатки
     |";
     Запрос.УложитьСписокОбъектов(спПодр,"#ВыбСклад","Подразделения");
     Запрос.УстановитьТекстовыйПараметр("ВыбНоменклатура", ВыбНоменклатура);
     ТЗ = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
     ТЗ_Наличие.УдалитьСтроки();
     Для Н=1 По ТЗ.КоличествоСтрок() Цикл
           ТЗ.ПолучитьСтрокуПоНомеру(Н);
           Кол  = ТЗ.ОстатокТовара;
           Подр = ТЗ.Склад;
           МинОстаток = ВыбНоменклатура.МинимальныйОстаток; 
           КонтрольМинОстатка = Подр.КонтрольМинОстатка;
           Разница = 0;
           Если (КонтрольМинОстатка = 1) И (МинОстаток <> 0) Тогда
                 Разница = Кол - МинОстаток;
           КонецЕсли;      
           Если Кол<>0 Тогда
                 ТЗ_Наличие.НоваяСтрока();
                 ТЗ_Наличие.Склад=Подр;
                 ТЗ_Наличие.Количество=Кол;
                 Если Разница < 0 Тогда
                       ТЗ_Наличие.Пикт = 35;
                 КонецЕсли;      
           КонецЕсли;
     КонецЦикла;
... и получаю, что штатное средство работает быстрее, нежели прямой запрос.
Отсюда вопросы:
1.  Всегда ли целесообразно использовать прямые запросы? Или в отдельных случаях необходимо обходиться штатными средствами 1С?
  
Наверх
 
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #1 - 27. Марта 2008 :: 07:33
Печать  
Считай разницу непосредственно в прямом запросе. И Кол там всегда <> 0..
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #2 - 27. Марта 2008 :: 07:38
Печать  
berezdetsky писал(а) 27. Марта 2008 :: 07:33:
Считай разницу непосредственно в прямом запросе. И Кол там всегда <> 0..

+1
На всякий случай: а разве дату получения остатка не нужно указывать ?
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #3 - 27. Марта 2008 :: 07:39
Печать  
Да и код
Код
Выбрать все
Для Н=1 По ТЗ.КоличествоСтрок() Цикл
	     ТЗ.ПолучитьСтрокуПоНомеру(Н); 


очень медленный.
Намного шустрее (для средних и больших таблиц) ВыбратьСтроки() и ПолучитьСтроку()
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer &amp;&amp; tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #4 - 27. Марта 2008 :: 07:51
Печать  
artbear писал(а) 27. Марта 2008 :: 07:38:
а разве дату получения остатка не нужно указывать ?

Если дата не указана, остатки считаются на ТА.
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
Kondarat
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 83
Зарегистрирован: 21. Декабря 2007
Re: Прямой запрос и штатное средство
Ответ #5 - 27. Марта 2008 :: 08:04
Печать  
Считай разницу непосредственно в прямом запросе. И Кол там всегда <> 0..

Помоги как.  Хотя бы направление. Мои знания пока в этом деле весьма и весьма..
  
Наверх
 
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #6 - 27. Марта 2008 :: 08:47
Печать  
Как-то так:
Код
Выбрать все
|Select
|    Номенклатура [Товар $Справочник.Номенклатура],
|    Подразделение [Склад $Справочник.Подразделения],
|    КоличествоОстаток ОстатокТовара,
|    CASE WHEN ($Подразделения.КонтрольМинОстатка = 1) AND ($Номенклатура.МинимальныйОстаток <> 0)
|	  THEN (остатки.КоличествоОстаток - $Номенклатура.МинимальныйОстаток)
|	  ELSE 0
|    END Разница
|FROM
|    $РегистрОстатки.Склад(,,
|	  (Номенклатура = :ВыбНоменклатура) And Подразделение in (Select val from #ВыбСклад),
|	  (Подразделение, Номенклатура),
|	  Количество
|    ) остатки
|    INNER JOIN $Справочник.Подразделения AS Подразделения (nolock) ON остатки.Подразделение = Подразделения.ID
|    INNER JOIN $Справочник.Номенклатура AS Номенклатура (nolock) ON остатки.Номенклатура = Номенклатура.ID  


А если абсолютное значение разницы не нужно, то
Код
Выбрать все
|    CASE WHEN ($Подразделения.КонтрольМинОстатка = 1) AND (остатки.КоличествоОстаток < $Номенклатура.МинимальныйОстаток)
|	  THEN 35
|	  ELSE  0
|    END Пикт 

  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
leshik
1c++ donor
Отсутствует



Сообщений: 820
Местоположение: Пятигорск
Зарегистрирован: 22. Апреля 2007
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #7 - 27. Марта 2008 :: 08:51
Печать  
А разве параметризированный запрос не быстрее будет работать?
  
Наверх
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #8 - 27. Марта 2008 :: 09:08
Печать  
leshik писал(а) 27. Марта 2008 :: 08:51:
А разве параметризированный запрос не быстрее будет работать?

Там экономия на времени компиляции, а не на времени выполнения. Если в #0 речь идёт о форме списка, конечно, подготовленный запрос или RPCMode будет полезно.
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
Kondarat
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 83
Зарегистрирован: 21. Декабря 2007
Re: Прямой запрос и штатное средство
Ответ #9 - 27. Марта 2008 :: 10:03
Печать  
berezdetsky писал(а) 27. Марта 2008 :: 09:08:
leshik писал(а) 27. Марта 2008 :: 08:51:
А разве параметризированный запрос не быстрее будет работать?

Там экономия на времени компиляции, а не на времени выполнения. Если в #0 речь идёт о форме списка, конечно, подготовленный запрос или RPCMode будет полезно.


Точно, речь идет о форме списка. Пытаюсь сделать подготовленный запрос так:
     ТекстЗапроса = "
     |@Подразделение = ?
     |@Номенклатура = ?
     |Select 
     |    Номенклатура [Товар $Справочник.Номенклатура], 
     |    Подразделение [Склад $Справочник.Подразделения],   
     |    КоличествоОстаток ОстатокТовара,
     |    CASE WHEN ($Подразделения.КонтрольМинОстатка = 1) AND (остатки.КоличествоОстаток < $Номенклатура.МинимальныйОстаток)
     |        THEN 35
     |        ELSE  0
     |    END Пикт      
     |FROM
     |    $РегистрОстатки.Склад(,,
     |        (Номенклатура = @Номенклатура) And (Подразделение = @Подразделение),
     |        (Подразделение, Номенклатура), 
     |        Количество
     |    ) остатки
     |    INNER JOIN $Справочник.Подразделения AS Подразделения (nolock) ON остатки.Подразделение = Подразделения.ID
     |    INNER JOIN $Справочник.Номенклатура AS Номенклатура (nolock) ON остатки.Номенклатура = Номенклатура.ID 
     |";
     Запрос.Подготовить(ТекстЗапроса);
    Запрос.ПостроитьПараметры();
     Запрос.УстПараметр(1, СпПодр);
               Запрос.УстПараметр(2, ВыбНоменклатура);
              ТЗ = Запрос.ВыполнитьИнструкцию();

и получаю ошибку:
ТЗ = Запрос.ВыполнитьИнструкцию();
{E:\ПРОСТОТЕСТ.ERT(81)}: State 07009, native 0, message [Microsoft][ODBC SQL Server Driver]Недопустимый индекс дескриптора

Что-то не так. Но что?
  
Наверх
 
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #10 - 27. Марта 2008 :: 10:12
Печать  
А как же
Подразделение in (Select val from #ВыбСклад)
?  Ты теперь и подразделения в цикле перебираешь? Улыбка Верни как было и заполняй #ВыбСклад один раз при открытии формы списка.
И пробуй для начала не подготовленные запросы, а RPCMode - оно проще в использовании.
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
Kondarat
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 83
Зарегистрирован: 21. Декабря 2007
Re: Прямой запрос и штатное средство
Ответ #11 - 27. Марта 2008 :: 10:20
Печать  
berezdetsky писал(а) 27. Марта 2008 :: 10:12:
А как же
Подразделение in (Select val from #ВыбСклад)
?  Ты теперь и подразделения в цикле перебираешь? Улыбка Верни как было и заполняй #ВыбСклад один раз при открытии формы списка.
И пробуй для начала не подготовленные запросы, а RPCMode - оно проще в использовании.


RPCMode - Это значит Запрос.РежимRPC(1), так? Или это нечто другле?

  
Наверх
 
IP записан
 
Kondarat
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 83
Зарегистрирован: 21. Декабря 2007
Re: Прямой запрос и штатное средство
Ответ #12 - 27. Марта 2008 :: 10:29
Печать  
berezdetsky писал(а) 27. Марта 2008 :: 10:12:
А как же
Подразделение in (Select val from #ВыбСклад)
?  Ты теперь и подразделения в цикле перебираешь? Улыбка Верни как было и заполняй #ВыбСклад один раз при открытии формы списка.
И пробуй для начала не подготовленные запросы, а RPCMode - оно проще в использовании.


Вот так все работает:
Код
Выбрать все
	ТекстЗапроса = "
	|Select
	|    Номенклатура [Товар $Справочник.Номенклатура],
	|    Подразделение [Склад $Справочник.Подразделения],
	|    КоличествоОстаток ОстатокТовара,
	|    CASE WHEN ($Подразделения.КонтрольМинОстатка = 1) AND (остатки.КоличествоОстаток < $Номенклатура.МинимальныйОстаток)
	|	  THEN 35
	|	  ELSE  0
	|    END Пикт
	|FROM
	|    $РегистрОстатки.Склад(,,
	|	  (Номенклатура = :ВыбНоменклатура) And Подразделение in (Select val from #ВыбСклад),
	|	  (Подразделение, Номенклатура),
	|	  Количество
	|    ) остатки
	|    INNER JOIN $Справочник.Подразделения AS Подразделения (nolock) ON остатки.Подразделение = Подразделения.ID
	|    INNER JOIN $Справочник.Номенклатура AS Номенклатура (nolock) ON остатки.Номенклатура = Номенклатура.ID
	|";

	Запрос.УложитьСписокОбъектов(спПодр,"#ВыбСклад","Подразделения");
	Запрос.УстановитьТекстовыйПараметр("ВыбНоменклатура", ВыбНоменклатура);
	Запрос.РежимRPC(1);
	ТЗ = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);
	ТЗ_Наличие.УдалитьСтроки();
	ТЗ.ВыбратьСтроки();
	Пока ТЗ.ПолучитьСтроку() = 1 Цикл
			ТЗ_Наличие.НоваяСтрока();
			ТЗ_Наличие.Склад = ТЗ.Склад;
			ТЗ_Наличие.Количество = ТЗ.ОстатокТовара;
			ТЗ_Наличие.Пикт = ТЗ.Пикт;
	КонецЦикла;
 



спПодр - это список Подразделений, который заполняется в ПриОткрытии
ВыбНоменклатура - пока только реквизит на тестовой обработке.

Но замеры показывают, что это в 2 раза медленее, чем штатно как в 0. Как ускорить? Есть ли такая возможность, или нет?

  
Наверх
 
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Прямой запрос и штатное средство
Ответ #13 - 27. Марта 2008 :: 10:39
Печать  
Вот это:
Запрос.УложитьСписокОбъектов(спПодр,"#ВыбСклад","Подразделения");
перенеси в ПриОткрытии.

Если в ТЗ_Наличие колонок, кроме перечисленных в коде, нет - выгружай результат запроса сразу туда, без промежуточной ТЗ.

Если ТЗ_Наличие нужна только для отображения (без постобработки) - убери типизацию:
Код
Выбрать все
|Select  
|    RTrim(Номенклатура.DESCR) Товар,
|    RTrim(Подразделения.DESCR) Склад, 



И зачем в запросе поле Товар, если он там только один?
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
Kondarat
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 83
Зарегистрирован: 21. Декабря 2007
Re: Прямой запрос и штатное средство
Ответ #14 - 27. Марта 2008 :: 11:01
Печать  
berezdetsky писал(а) 27. Марта 2008 :: 10:39:
Вот это:
Запрос.УложитьСписокОбъектов(спПодр,"#ВыбСклад","Подразделения");
перенеси в ПриОткрытии.

Если в ТЗ_Наличие колонок, кроме перечисленных в коде, нет - выгружай результат запроса сразу туда, без промежуточной ТЗ.

Если ТЗ_Наличие нужна только для отображения (без постобработки) - убери типизацию:
Код
Выбрать все
|Select  
|    RTrim(Номенклатура.DESCR) Товар,
|    RTrim(Подразделения.DESCR) Склад, 



И зачем в запросе поле Товар, если он там только один?



Запрос.УложитьСписокОбъектов(спПодр,"#ВыбСклад","Подразделения");
перенес в ПриОткрытии, эффект следующий: если первый раз выполнить прямой запрос, то он по времени несколько дольше, чем штатно, а затем в 3 раза быстрее. С чем это связано?
ТЗ_Наличие нужна для пост обработки, т. к. там еще должен отображаться резерв и при необходимости его расшифровка.

Товар действительно не нужен - убрал.

ОГРОМНОЕ ТЕБЕ СПАСИБО. Только из одной ветки с твоей помощю узнал много больше, чем из доки.

  
Наверх
 
IP записан
 
Kondarat
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 83
Зарегистрирован: 21. Декабря 2007
Re: Прямой запрос и штатное средство
Ответ #15 - 27. Марта 2008 :: 11:48
Печать  
Добавил в запрос выборку по второму регистру. Работает.
Гляньте кто-нибудь, все ли правильно и оптимально с точки зрения написания
прямых запросов

Код
Выбрать все
	ТекстЗапроса = "
	|Select
	|    Остатки.Подразделение [Склад $Справочник.Подразделения],
	|    Остатки.КоличествоОстаток Количество,
	|    Резервы.КоличествоОстаток Резерв,
	|    CASE WHEN ($Подразделения.КонтрольМинОстатка = 1) AND (остатки.КоличествоОстаток < $Номенклатура.МинимальныйОстаток)
	|	  THEN 35
	|	  ELSE  0
	|    END Пикт
	|FROM
	|    $РегистрОстатки.Склад(,,
	|	  (Номенклатура = :ВыбНоменклатура) And Подразделение in (Select val from #ВыбСклад),
	|	  (Подразделение, Номенклатура),
	|	  Количество
	|    ) Остатки
	|    LEFT JOIN $РегистрОстатки.Резерв(,,
	|	  (Номенклатура = :ВыбНоменклатура) And Подразделение in (Select val from #ВыбСклад),
	|	  (Подразделение, Номенклатура),
	|	  Количество
	|    ) Резервы
	|    ON Резервы.Номенклатура = Остатки.Номенклатура
    |    AND Резервы.Подразделение = Остатки.Подразделение
	|    INNER JOIN $Справочник.Подразделения AS Подразделения (nolock) ON Остатки.Подразделение = Подразделения.ID
	|    INNER JOIN $Справочник.Номенклатура AS Номенклатура (nolock) ON Остатки.Номенклатура = Номенклатура.ID
	|";

 

  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 
ОтправитьПечать