Переключение на Главную Страницу Страницы: [1] 2 3 ... 8 ОтправитьПечать
Очень популярная тема (более 25 ответов) Выборка остатков прямым запросом (число прочтений - 30138 )
Foma
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 61
Зарегистрирован: 16. Сентября 2010
Выборка остатков прямым запросом
16. Сентября 2010 :: 04:56
Печать  
Перешли с dbf на SQL (1С 7.7). Все по скорости нормально работает, кроме одной вещи: в списке справочника Номенклатура (подбор из документа) в колонке остатки рассчитывается остаток на ТА и дико тормозит. Попытался сделать это прямым запросом:

//********************************************************
Функция ВернутьОстаток(Знач парНом, Знач парСклад)
     Перем Таб_Ост, Таб_Рез;
     
     ТекстЗапроса = "
     |SELECT
     |      $Рег.Количество as Количество
     |FROM
     |      $Регистр.ОстаткиТМЦ as Рег
     |WHERE
     |      $Рег.Номенклатура = ? AND
     |      $Рег.Склад IN (SELECT Val From #ГруппаСкладов) AND
     |      $Рег.Фирма IN (SELECT Val From #ГруппаФирм) ";
     
     RS.УложитьСписокОбъектов(парСклад,"#ГруппаСкладов","Склады");
     RS.УложитьСписокОбъектов(ФирмаДляОстатковТМЦ,"#ГруппаФирм","Фирмы");
     RS.Подготовить(ТекстЗапроса);
     RS.ПостроитьПараметры();
     RS.УстПараметр(1,парНом);
     
     КолОст = RS.ВыполнитьСкалярный();
     
     Возврат КолОст;
КонецФункции // ВернутьОстаток

парНом - элемент Спр.Номенклатура
парСклад - СписокЗначений с элементами типа Спр.Склады
ФирмаДляОстатковТМЦ - СписокЗначений с элементами типа Спр.Фирмы

При открытии списка справочника и развертке до элементов 1С вылетает с ошибкой
"подключение занято до получения результатов для другого hstmt"

В чем может быть дело? Раньше прямыми запросами не пользовался никогда. Просьба помочь...
  
Наверх
 
IP записан
 
pavel_tr
Senior Member
****
Отсутствует



Сообщений: 279
Местоположение: Казань
Зарегистрирован: 14. Октября 2006
Пол: Мужской
Re: Выборка остатков прямым запросом
Ответ #1 - 16. Сентября 2010 :: 05:47
Печать  
Забыли условие на period, это как минимум и лучше написать sum($Рег.Количество)
У нас так (это в ПриНачалеРаботыСистемы()):
Код
Выбрать все
Перем глОстТовара  Экспорт;

стрдатыТА=строка(формат(НачМесяца(ПолучитьДатуТА()),"ДГГГГММДД"));

глОстТовара = СоздатьОбъект("ODBCRecordset");  
ТекстЗапроса = "
|SELECT
|	SUM($Рег.Остаток)
|FROM
|	$РегистрИтоги.Остатки Рег (NoLock)
|WHERE
|	Рег.PERIOD='"+стрдатыТА+"' AND
|	$Рег.Товар = ? AND  
|	$Рег.Склад = ?
|";

Если глОстТовара.Подготовить(ТекстЗапроса)=0 тогда
	сообщить("Ошибка подготовки запроса остатков по складу (гл)! "+глОстТовара.ПолучитьОписаниеОшибки()+РазделительСтрок+"Свяжитесь с админитсратором!!!");
КонецЕсли;
глОстТовара.ПостроитьПараметры();  



А в форме списка - вызов:
Код
Выбрать все
Функция глОстатокТовара(товар,склад) Экспорт
	ост=0;
	глОстТовара.УстПараметр(1, товар);
	глОстТовара.УстПараметр(2, склад);
	ост=глОстТовара.ВыполнитьСкалярный();
	Возврат ост;
КонецФункции  

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



Сообщений: 136
Местоположение: Липецк
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Выборка остатков прямым запросом
Ответ #2 - 16. Сентября 2010 :: 05:51
Печать  
Запрос возвращает много строк. Может
Код
Выбрать все
SUM($Рег.Количество) as Количество 


Упс, не успел
  

Необходимо время, чтобы восстановить хаос. (с) Дж. Буш (младший)
Наверх
 
IP записан
 
pavel_tr
Senior Member
****
Отсутствует



Сообщений: 279
Местоположение: Казань
Зарегистрирован: 14. Октября 2006
Пол: Мужской
Re: Выборка остатков прямым запросом
Ответ #3 - 16. Сентября 2010 :: 05:59
Печать  
Цитата из учебника: (подчёркивания мои)

Глава 5: Вывод остатков в форме списка
Для этой цели больше всего подходят параметризированные запросы(только для СКЛ!).

Выглядит такой запрос так:
Код
Выбрать все
ТекстЗапроса = "
|SELECT
|	$Рег.Количество as Количество
|FROM
|	$РегистрИтоги.ОстаткиТоваров as Рег
|WHERE
|	Рег.Period = {d’2005-01-01’} AND
|	$Рег.Склад = ? AND
|	$Рег.Товар = ?"; 



Суть состоит в том, что запрос компилируется только 1 раз, а в остальные разы меняются только параметры, помеченные знаком “?”. За счет этого достигается некоторый выигрыш в скорости.

Для того, чтобы воспользоваться этой хорошей штукой поступим следующим образом:
В модуле формы заведем переменную RS. В процедуре ПриОткрытии() проинициализируем ее:

Код
Выбрать все
Процедура ПриОткрытии()
	RS = СоздатьОбъект("ODBCRecordset");
	ТекстЗапроса = // … смотри выше
	RS.Подготовить(ТекстЗапроса);
	RS.ПостроитьПараметры();
	RS.УстПараметр(1, ВыбСклад);
КонецПроцедуры 


В качестве периода в запросе будем использовать начало текущего месяца.
Добавим текстовую колонку, в которой пропишем формулу

Код
Выбрать все
Функция ПолучитьОстаток()
	RS.УстПараметр(2, ТекущийЭлемент());
	Возврат RS.ВыполнитьСкалярный();
КонецФункции 



Здесь нужно помнить, что запрос нужно писать такой, который вернет только одну позицию. Это можно всегда сделать с помощью функции SUM(). Опять же для того чтобы это быстро бегало необходимо наиболее точно попасть в индекс, т.е указать все поля участвующие в индексе. В данном случае это все измерения.

В этом примере мы использовали метод ВыполнитьСкалярный() который возвращает не таблицу, а единственное значение или структуры, если выбирается несколько колонок.
Вы конечно спросите: А почему не использовали ВТ Остатки? Да, это единственное место где ее применять не очень хорошо, т.к. там присутствует метод GROUP BY, что несколько снижает скорость работы.
  
Наверх
 
IP записан
 
Foma
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 61
Зарегистрирован: 16. Сентября 2010
Re: Выборка остатков прямым запросом
Ответ #4 - 16. Сентября 2010 :: 06:52
Печать  
Добавил SUM - заработало, только медленно. Логично, что инициализацию запроса можно вынести в глобальный модуль или в ПриОткрытии формы.
Сделал так.
ПриОткрытии:
ТекстЗапроса = "
     |SELECT
     |      SUM($Рег.Количество) as Количество
     |FROM
     |      $Регистр.ОстаткиТМЦ as Рег
     |WHERE
     |      $Рег.Номенклатура = ? AND
     |      $Рег.Склад IN (SELECT Val From #ГруппаСкладов) AND
     |      $Рег.Фирма IN (SELECT Val From #ГруппаФирм) ";
     
     RS.УложитьСписокОбъектов(ФирмаДляОстатковТМЦ,"#ГруппаФирм","Фирмы");
     RS.Подготовить(ТекстЗапроса);
     RS.ПостроитьПараметры();

А функцию, возвращающую остаток:
//********************************************************
Функция ВернутьОстаток(Знач парНом, Знач парСклад, парСтрокой)
     
RS.УложитьСписокОбъектов(парСклад,"#ГруппаСкладов","Склады");
     RS.УстПараметр(1,парНом);
     
     КолОст = RS.ВыполнитьСкалярный();
     
     Возврат СокрЛП(КолОст);
КонецФункции // ВернутьОстаток

При работе 1С выдает ошибку:
RS.УстПараметр(1,парНом);
{Справочник.Номенклатура.ФормаСписка.ДляПодбора.Модуль(571)}: Недопустимое значение индекса параметра

И не понятно зачем Period. Ведь выборка на ТА идет
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Выборка остатков прямым запросом
Ответ #5 - 16. Сентября 2010 :: 06:55
Печать  
Улыбка)
без периода тебе подсчитает сумму всех промежуточных итогов с начала ведения базы.
  
Наверх
 
IP записан
 
trad
1c++ power user
1c++ donor
1c++ moderator
Отсутствует



Сообщений: 3050
Местоположение: Киров
Зарегистрирован: 23. Мая 2006
Пол: Мужской
Re: Выборка остатков прямым запросом
Ответ #6 - 16. Сентября 2010 :: 07:07
Печать  
Цитата:
сумму всех промежуточных итогов

если бы еще итогов... Улыбка
  

1&&2&&3
Наверх
 
IP записан
 
Foma
Junior Member
**
Отсутствует


1C++ rocks!

Сообщений: 61
Зарегистрирован: 16. Сентября 2010
Re: Выборка остатков прямым запросом
Ответ #7 - 16. Сентября 2010 :: 07:09
Печать  
И почему
стрдатыТА=строка(формат(НачМесяца(ПолучитьДатуТА()),"ДГГГГММДД"));
а не
стрдатыТА=строка(формат(ПолучитьДатуТА(),"ДГГГГММДД"));
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Выборка остатков прямым запросом
Ответ #8 - 16. Сентября 2010 :: 07:17
Печать  
trad писал(а) 16. Сентября 2010 :: 07:07:
Цитата:
сумму всех промежуточных итогов

если бы еще итогов... Улыбка


а чорт, вижу, что про останки говорят, а на сам текст запроса и не глядел даже .. Улыбка
  
Наверх
 
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: Выборка остатков прямым запросом
Ответ #9 - 16. Сентября 2010 :: 07:20
Печать  
Foma писал(а) 16. Сентября 2010 :: 07:09:
И почему
стрдатыТА=строка(формат(НачМесяца(ПолучитьДатуТА()),"ДГГГГММДД"));
а не
стрдатыТА=строка(формат(ПолучитьДатуТА(),"ДГГГГММДД"));

Да потому что надо приводить к типу который в sql таблице.
поле PERIOD имеет тип DATETIME ( полученную строку надо
обрамлять в одиночные кавычки еще лучше явный cast ).

Раз заговорил о скорости то когда склад ( фирма ) только один элемент(это не папка)  вместо in надо формировать =

Еще совет ставь в текст
RS.Отладка(1);
и выполняй получившийся запрос через qa.

Также для единичного запроса не имеет смысла строить параметризированный запрос ( где есть ? )

PS ну и в #4 надо
$РегистрИтоги.ОстаткиТМЦ as Рег
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Выборка остатков прямым запросом
Ответ #10 - 16. Сентября 2010 :: 07:20
Печать  
Foma писал(а) 16. Сентября 2010 :: 07:09:
И почему
стрдатыТА=строка(формат(НачМесяца(ПолучитьДатуТА()),"ДГГГГММДД"));
а не
стрдатыТА=строка(формат(ПолучитьДатуТА(),"ДГГГГММДД"));



Фома, а не пробовал в начале хотя бы разобраться, как устроен регистр в 1с ?
Что регистр, это 2 таблички, RA - для всех движений регистра, а RG - для промежуточных итогов.
http://www.script-coding.info/v77tables.html#3.4.
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Выборка остатков прямым запросом
Ответ #11 - 16. Сентября 2010 :: 07:23
Печать  
Z1 писал(а) 16. Сентября 2010 :: 07:20:
Да потому что надо приводить к типу который в sql таблице.



Да не, он просто не понимает, почему нужно начало месяца пихать, а не саму дату ТА..
Про периодичность хранения останков не слышал автор видать, и со структурой регистра не знаком.



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


1C++ rocks!

Сообщений: 61
Зарегистрирован: 16. Сентября 2010
Re: Выборка остатков прямым запросом
Ответ #12 - 16. Сентября 2010 :: 07:36
Печать  
Со структурой регистров знаком и что это 2 файлика тоже знаю. С 1С++ не знаком вообще. Вот и прошу помочь разобраться.
Честно говоря думал, что 1с++ как-то скрывает внутрянку и что прямыми запросами вытащить остатки на ТА довольно просто. Видимо я ошибался.
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Выборка остатков прямым запросом
Ответ #13 - 16. Сентября 2010 :: 07:43
Печать  
Foma писал(а) 16. Сентября 2010 :: 07:36:
Со структурой регистров знаком и что это 2 файлика тоже знаю. С 1С++ не знаком вообще. Вот и прошу помочь разобраться.
Честно говоря думал, что 1с++ как-то скрывает внутрянку и что прямыми запросами вытащить остатки на ТА довольно просто. Видимо я ошибался.


И сейчас ошибаешься. Еще проще чем ты думаешь.
Посмотри FAQ по прямым запросам - там всё есть.
  
Наверх
 
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: Выборка остатков прямым запросом
Ответ #14 - 16. Сентября 2010 :: 07:50
Печать  
Foma писал(а) 16. Сентября 2010 :: 07:36:
Со структурой регистров знаком и что это 2 файлика тоже знаю. С 1С++ не знаком вообще. Вот и прошу помочь разобраться.
Честно говоря думал, что 1с++ как-то скрывает внутрянку и что прямыми запросами вытащить остатки на ТА довольно просто. Видимо я ошибался.


Цитата:
Со структурой регистров знаком и что это 2 файлика тоже знаю.

раз речь об sql то это не два файла а две таблицы.


Цитата:
1с++ как-то скрывает внутрянку

1с++ это практически чистый t-sql.
добавлен метапарсер подстановка имен в терминах 1с
( все что начинается с $ ).
Также результат выполнения запроса можно получить типизированным в объектах 1с ( наверно это непонятно и непривычно)


1с хранит итоги по месяцам ( в 99% процентах ).
итоги хранятся в таблице rg...
Поля этой таблицы
PERIOD
все измерения
все ресурсы

итоги на ТА хранятся в последнем ( по возрастанию периоде ).
поэтому для получения остатков на ТА надо в WHERE надо обязательно указать этот период.
например
WHERE PERIOD =  cast ('20100901' as datetime )  and ...
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 3 ... 8
ОтправитьПечать