Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема Метод ВыбратьДвижения() по регистру через прямой запрос SQL (число прочтений - 3926 )
Looking
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 33
Зарегистрирован: 11. Апреля 2007
Метод ВыбратьДвижения() по регистру через прямой запрос SQL
26. Июня 2011 :: 09:55
Печать  
Конфигурация ПУБ, БД SQL.
Написал функцию для контроля просроченной задолженности в Модуле документа РеализацияПродукции, через метод ВыбратьДвижения(). Работает медленно, задержка порядка 5 секунд. Задержка в 5 секунд именно в строке
Регистры.РасчетыСПокупателями.ВыбратьДвижения(,Тек ущийДокумент(),);

Можно-ли выбрать движения регистра прямым запросом SQL? Помогите примером, пожалуйста.

Мой код:

Код
Выбрать все
Если Константа.КонтрольКредитаПокупателей=1 Тогда

Если ПустоеЗначение(Договор)=0 Тогда
ДопСведенияДоговоров=СоздатьОбъект("Справочник.МДВ ДоговорыДополнительныеСведения");
ДопСведенияДоговоров.ИспользоватьВладельца(Договор );
ДопСведенияДоговоров.ВыбратьЭлементы();
Если ДопСведенияДоговоров.ПолучитьЭлемент()=1 Тогда
ПеремКонтролироватьКредит=ДопСведенияДоговоров.Кон тролироватьКредит;
ПеремГлубинаКредита=ДопСведенияДоговоров.ГлубинаКр едита;
КонецЕсли;
КонецЕсли;

Если ПеремКонтролироватьКредит=1 Тогда

Регистры=СоздатьОбъект("Регистры");
Регистры.РасчетыСПокупателями.УстановитьЗначениеФи льтра("Контрагент", Контрагент, 1);
Регистры.РасчетыСПокупателями.УстановитьЗначениеФи льтра("Договор", Договор, 1);

Если ИтогиАктуальны() = 0 Тогда
Регистры.РасчетыСПокупателями.ВременныйРасчет(1);
Регистры.Актуальность(1);
Регистры.РассчитатьРегистрыНа(ТекущийДокумент());
КонецЕсли;

ДолгПоДоговору=Регистры.РасчетыСПокупателями.Сводн ыйОстаток(Контрагент,Договор,,,,,"Долг");
Если ДолгПоДоговору<0 Тогда
ДолгПоДоговору=-ДолгПоДоговору;
//Сообщить("ДолгПоДоговору "+ДолгПоДоговору);

ТЗДокЗадолж=СоздатьОбъект("ТаблицаЗначений");
ТЗДокЗадолж.НоваяКолонка("Док");
ТЗДокЗадолж.НоваяКолонка("СуммаДок");
ТЗДокЗадолж.НоваяКолонка("СуммаВозвр");


Регистры.РасчетыСПокупателями.ОбратныйПорядок(1);

ДокПодч=СоздатьОбъект("Документ");
ДолгПоДокументам=0;
Регистры.РасчетыСПокупателями.ВыбратьДвижения(,Тек ущийДокумент(),);
Пока Регистры.РасчетыСПокупателями.ПолучитьДвижение()=1 Цикл
Если Регистры.РасчетыСПокупателями.Расход=1 Тогда
ПеремТекДокРРП=Регистры.РасчетыСПокупателями.Текущ ийДокумент();
ПеремВидТекДокРРП=ПеремТекДокРРП.Вид();
Если (ПеремВидТекДокРРП="РеализацияПродукции") или (ПеремВидТекДокРРП="РеализацияМатериалов")
или (ПеремВидТекДокРРП="РеализацияРаботПоНормам") или (ПеремВидТекДокРРП="ПередачаОС")
или (ПеремВидТекДокРРП="ВводОстатковПокупателей") Тогда
ПеремСуммаДок=Регистры.РасчетыСПокупателями.Долг;
ДолгПоДокументам=ДолгПоДокументам+ПеремСуммаДок;

ТЗДокЗадолж.НоваяСтрока();
ТЗДокЗадолж.Док=ПеремТекДокРРП;
ТЗДокЗадолж.СуммаДок=ПеремСуммаДок;
ТЗДокЗадолж.СуммаВозвр=0;


Если (ПеремВидТекДокРРП="РеализацияПродукции") или (ПеремВидТекДокРРП="РеализацияМатериалов") Тогда
ДокПодч.ВыбратьПодчиненныеДокументы(,,ПеремТекДокР РП);
Пока ДокПодч.ПолучитьДокумент()=1 Цикл
Если ДокПодч.Вид()="ВозвратОтПокупателя" Тогда
Если ДокПодч.Проведен()=1 Тогда
ПеремСуммаВозвр=ДокПодч.Итог("Всего");
ДолгПоДокументам=ДолгПоДокументам-ПеремСуммаВозвр;

ТЗДокЗадолж.НоваяСтрока();
ТЗДокЗадолж.Док=ПеремТекДокРРП;
ТЗДокЗадолж.СуммаДок=0;
ТЗДокЗадолж.СуммаВозвр=ПеремСуммаВозвр;


//Сообщить("Вычтен возврат: "+ДокПодч.Итог("Всего"));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
//Сообщить("ДолгПоДокументам "+ДолгПоДокументам);
//Сообщить(Регистры.РасчетыСПокупателями.ТекущийДоку мент());
Если ДолгПоДокументам>=ДолгПоДоговору Тогда
Прервать;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;

Если ТЗДокЗадолж.КоличествоСтрок()>0 Тогда
ТЗДокЗадолж.Свернуть("Док","СуммаДок,СуммаВозвр");
ТЗДокЗадолж.НоваяКолонка("ДатаДок");
ТЗДокЗадолж.НоваяКолонка("СуммаДокМинусВозвр");
ТЗДокЗадолж.ВыбратьСтроки();
Пока ТЗДокЗадолж.ПолучитьСтроку()=1 Цикл
ТЗДокЗадолж.ДатаДок=ТЗДокЗадолж.Док.ДатаДок;
ТЗДокЗадолж.СуммаДокМинусВозвр=ТЗДокЗадолж.СуммаДо к-ТЗДокЗадолж.СуммаВозвр;
КонецЦикла;
Для Сч=-ТЗДокЗадолж.КоличествоСтрок() по -1 Цикл
Если ТЗДокЗадолж.ПолучитьЗначение(-Сч,"СуммаДокМинусВозвр")=0 Тогда
ТЗДокЗадолж.УдалитьСтроку(-Сч);
КонецЕсли;
КонецЦикла;

ПеремКонтрольнаяДата=(ДатаДок-ПеремГлубинаКредита);

ПеремПризнакПросрочЗадолж=0;
ТЗДокЗадолж.Сортировать("ДатаДок");
ТЗДокЗадолж.ВыбратьСтроки();
Пока ТЗДокЗадолж.ПолучитьСтроку()=1 Цикл
Если ТЗДокЗадолж.ДатаДок<ПеремКонтрольнаяДата Тогда
ПеремПризнакПросрочЗадолж=1;
Прервать;
КонецЕсли;
КонецЦикла;

Если ПеремПризнакПросрочЗадолж=1 Тогда
Если Вопрос("У покупателя имеется просроченная задолженность! Показать отчёт о задолженности?",4)=6 Тогда
ТабЗП=СоздатьОбъект("Таблица");
ТабЗП.ИсходнаяТаблица(КаталогИБ()+"\ExtForms\MXLFo rms\ЗадолженностьПокупателяПодокументно.mxl");
ПчДок=СокрЛП(ТекущийДокумент());
ПЧВремя=ТекущийДокумент().ПолучитьВремя();
ПчДоговор="Договор: "+СокрЛП(Договор);
ПчДолгПоДоговору="Задолженность по договору: "+СокрЛП(ДолгПоДоговору)+" руб.";
ТабЗП.ВывестиСекцию("Шапка");
ПчНомППДок=0;

Если Константа.СортировкаДокЗадолжВОтчетеОЗадолжПокупат еляПоУбываниюДаты=1 Тогда
ТЗДокЗадолж.Сортировать("ДатаДок-");
КонецЕсли;

ТЗДокЗадолж.ВыбратьСтроки();
Пока ТЗДокЗадолж.ПолучитьСтроку()=1 Цикл
ПчНомППДок=ПчНомППДок+1;
ПчДатаДок=СокрЛП(ТЗДокЗадолж.ДатаДок);
ПчДокум=СокрЛП(ТЗДокЗадолж.Док);
ПчСуммаДокМинусВозвр=ТЗДокЗадолж.СуммаДокМинусВозв р;
ПчСуммаДок=ТЗДокЗадолж.СуммаДок;
ПчСуммаВозвр=ТЗДокЗадолж.СуммаВозвр;
ТабЗП.ВывестиСекцию("СтрокаДок");
КонецЦикла;

ПчСуммаДокМинусВозврИт=ТЗДокЗадолж.Итог("СуммаДокМ инусВозвр");
ПчСуммаДокИт=ТЗДокЗадолж.Итог("СуммаДок");
ПчСуммаВозврИт=ТЗДокЗадолж.Итог("СуммаВозвр");
ТабЗП.ВывестиСекцию("Итого");
ПчРуководительОтделаСбыта=ФИО(Константа.Руководите льОтделаСбыта.Получить(ДатаДок));
ПчОператорДиспСлужбы=Автор;
ТабЗП.ВывестиСекцию("Подвал");
 

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


I Love YaBB 2!

Сообщений: 33
Зарегистрирован: 11. Апреля 2007
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #1 - 26. Июня 2011 :: 09:58
Печать  
окончание кода

Код
Выбрать все
ТабЗП.Показать();
КонецЕсли;
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецЕсли;

КонецЕсли; //Если ДолгПоДоговору<0 Тогда
КонецЕсли; //Если ПеремКонтролироватьКредит=1 Тогда
КонецЕсли; 

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


I Love YaBB 2!

Сообщений: 33
Зарегистрирован: 11. Апреля 2007
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #2 - 27. Июня 2011 :: 03:57
Печать  
Наверное я напрасно весь код привёл, меня интересует, как можно реализовать следующий кусок кода прямым запросом, и даст-ли это навскидку существенное ускорение?
В этом куске кода - первое - выборка движений регистра, второе - выборка подчинённых документов. Эти методы имеют аналоги в виде прямых запросов?

Код
Выбрать все
Регистры=СоздатьОбъект("Регистры");
    Регистры.РасчетыСПокупателями.УстановитьЗначениеФильтра("Контрагент", Контрагент, 1);
    Регистры.РасчетыСПокупателями.УстановитьЗначениеФильтра("Договор", Договор, 1);

Если ИтогиАктуальны() = 0 Тогда
    Регистры.РасчетыСПокупателями.ВременныйРасчет(1);
    Регистры.Актуальность(1);
    Регистры.РассчитатьРегистрыНа(ТекущийДокумент());
КонецЕсли;

Регистры.РасчетыСПокупателями.ОбратныйПорядок(1);

ДокПодч=СоздатьОбъект("Документ");

Регистры.РасчетыСПокупателями.ВыбратьДвижения(,ТекущийДокумент(),);
    Пока Регистры.РасчетыСПокупателями.ПолучитьДвижение()=1 Цикл

ПеремТекДокРРП=Регистры.РасчетыСПокупателями.ТекущийДокумент();

ДокПодч.ВыбратьПодчиненныеДокументы(,,ПеремТекДокРРП);
	   Пока ДокПодч.ПолучитьДокумент()=1 Цикл

	   КонецЦикла;
КонецЦикла;
 



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



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #3 - 27. Июня 2011 :: 04:17
Печать  
Для начала, весь код в топку.
За вопрос в модуле проведения и рисование Таблиц - нужно увольнять с работы без объяснения причин за несоответствие занимаемой должности.
  
Наверх
 
IP записан
 
Looking
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 33
Зарегистрирован: 11. Апреля 2007
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #4 - 27. Июня 2011 :: 04:56
Печать  
Eprst писал(а) 27. Июня 2011 :: 04:17:
Для начала, весь код в топку.
За вопрос в модуле проведения и рисование Таблиц - нужно увольнять с работы без объяснения причин за несоответствие занимаемой должности.


код в части самого метода обратной выборки движений регистра и определению сумм возврата перебором подчинённых документов?

что касается вопроса, то при групповом перепроведении документов контроль просроченной задолженности выключается через значение Константы, ну а чем рисование таблицы по вопросу не устроило? тем более что документ уже не будет проводиться дальше, т.к. есть просрочка, цель рисования таблицы только в удобстве для пользователя, разве она в модуле проведения будет рисоваться медленнее чем во внешнем отчёте?
  
Наверх
 
IP записан
 
Eprst
God Member
*****
Отсутствует



Сообщений: 3397
Зарегистрирован: 08. Октября 2007
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #5 - 27. Июня 2011 :: 05:11
Печать  
Цитата:
без объяснения причин за несоответствие занимаемой должности


И групповое перепроведение тут не при чем, сами пользователи тебе яички быстрее дверкой прищемят за такой код, когда будут рыдать от постоянной транзакции.


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


I Love YaBB 2!

Сообщений: 33
Зарегистрирован: 11. Апреля 2007
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #6 - 27. Июня 2011 :: 05:13
Печать  
Eprst писал(а) 27. Июня 2011 :: 05:11:
Цитата:
без объяснения причин за несоответствие занимаемой должности


И групповое перепроведение тут не при чем, сами пользователи тебе яички быстрее дверкой прищемят за такой код, когда будут рыдать от постоянной транзакции.


понял, спасибо за науку  Смущённый
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #7 - 27. Июня 2011 :: 10:55
Печать  
Код
Выбрать все
Регистры.РасчетыСПокупателями.ВыбратьДвижения(,ТекущийДокумент(),);
Пока Регистры.РасчетыСПокупателями.ПолучитьДвижение()=1 Цикл
    ПеремТекДокРРП=Регистры.РасчетыСПокупателями.ТекущийДокумент();
    ДокПодч.ВыбратьПодчиненныеДокументы(,,ПеремТекДокРРП);
    Пока ДокПодч.ПолучитьДокумент()=1 Цикл

    КонецЦикла;
КонецЦикла; 



Ммм код, мягко говоря, шизофренический.
1) Нет проверки, что по данному документу выборку подчиненных уже просматривали.
2) Я с ходу не помню, но кажется на метод регистра ВыбратьДвижения() накладываемые фильтры (УстановитьЗначенияФильтра()) не влияют - а значит с ростом базы обход будет все более и более... эм... ****цовый.

3) ну и прямой запрос, соответственно, примерно такой, например:

Код
Выбрать все
ТекстЗапроса = "
|SELECT
|	IDDoc [Док $Документ],
|	IDDocDef Док_вид
|FROM
|	$Регистр.РасчетыСПокупателями рег (NoLock)
|WHERE
|	Date_Time_IDDOC <= :ПозицияПо
|GROUP BY
|	IDDoc, IDDocDef, Date_Time_IDDOC
|ORDER BY
|	Date_Time_IDDOC
|";
 



условия в Where добавляешь по вкусу.
PS у регистра может и не быть поля Date_Time_IDDoc (если не стоит галки "Быстрый отбор движений" и нет еще чего-то - кажется, отбора по движениям). Тогда к регистру делаешь джойн журнала и используешь поля журнала.
  
Наверх
 
IP записан
 
Satans Claws
God Member
*****
Отсутствует


1C++ rocks!

Сообщений: 721
Зарегистрирован: 29. Ноября 2010
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #8 - 28. Июня 2011 :: 01:59
Печать  
Вот так, если быть точнее.

ТекстЗапроса = "
|SELECT
|      IDDoc [Док $Документ],
|      IDDocDef Док_вид
|      sum($рег.Долг) Долг
|FROM
|      $Регистр.РасчетыСПокупателями рег (NoLock)
|WHERE
|      Date_Time_IDDOC < :ПозицияПо
|      And IdDocDef in ($ВидДокумента.РеализацияПродукции, $ВидДокумента.РеализацияМатериалов <, ...>)
|      And DebKred = 1
|      And $рег.Контрагент = :Контрагент
|      And $рег.Договор = :Договор
|Group By
|      IDDocDef, IDDoc, Date_Time_IDDOC
|ORDER BY
|      Date_Time_IDDOC
|";

Но некоторые моменты вызывают искреннее недоумение.
Например - Константа.СортировкаДокЗадолжВОтчетеОЗадолжПокупателяПоУбываниюДаты.
Это явно просится в настройки пользователя - но никак не в константы.
  
Наверх
 
IP записан
 
pvase
God Member
*****
Отсутствует



Сообщений: 923
Местоположение: Киев
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Метод ВыбратьДвижения() по регистру через прямой запрос SQL
Ответ #9 - 29. Июня 2011 :: 12:20
Печать  
Код
Выбрать все
// ===============================
Функция ПолучитьДвижениеДокумента(Док,ВидРегистра) Экспорт // : ТаблицаЗначений
	ИндРег = ВидРегистра;
	МДРег = Метаданные.Регистр(ИндРег);
	Если МДРег.Выбран() = 0 Тогда
		Возврат(0);
	КонецЕсли;
	ТекстЗП = "SELECT
	|	CAST(TabR.LineNo_ AS Char(9)) + Cast(TabR.ActNo AS Char(9)) AS ID,
	|	TabR.LineNo_ AS НомерСтрокиДокумента,
	|	TabR.ActNo AS НомерДвижения,
	|	TabR.DEBKRED AS Расход,
	|	CASE WHEN TabR.DEBKRED = 0 THEN '+' ELSE '-' END AS ПриходРасход";
	Для НомКол = 1 По МДРег.Измерение() Цикл
		МдКол = МДРег.Измерение(НомКол);
		ИндКол = МдКол.Идентификатор;
		СинКол = МдКол.Синоним;
		СинКол = ?(СокрЛП(СинКол) <> "",СинКол,ИндКол);
		ТипКол = МдКол.Тип;
		ВидКол = МдКол.Вид;
		ТипВид = ТипКол + ?(ВидКол <> "","."+ВидКол,"");
		ТекстЗП = ТекстЗП +",
		|	$TabR."+ИндКол+" AS ["+ИндКол+" $" + ТипВид + "]";


	КонецЦикла;
	Для НомКол = 1 По МДРег.Ресурс() Цикл
		МдКол = МДРег.Ресурс(НомКол);
		ИндКол = МдКол.Идентификатор;
		СинКол = МдКол.Синоним;
		СинКол = ?(СокрЛП(СинКол) <> "",СинКол,ИндКол);
		ТипКол = МдКол.Тип;
		ВидКол = МдКол.Вид;
		ТипВид = ТипКол + ?(ВидКол <> "","."+ВидКол,"");
		ТекстЗП = ТекстЗП +",
		|	$TabR."+ИндКол+" AS ["+ИндКол+" $" + ТипВид + "]";


	КонецЦикла;
	Для НомКол = 1 По МДРег.Реквизит() Цикл
		МдКол = МДРег.Реквизит(НомКол);
		ИндКол = МдКол.Идентификатор;
		СинКол = МдКол.Синоним;
		СинКол = ?(СокрЛП(СинКол) <> "",СинКол,ИндКол);
		ТипКол = МдКол.Тип;
		ВидКол = МдКол.Вид;
		ТипВид = ТипКол + ?(ВидКол <> "","."+ВидКол,"");
		ТекстЗП = ТекстЗП +",
		|	$TabR."+ИндКол+" AS ["+ИндКол+" $" + ТипВид + "]";


	КонецЦикла;
	ТекстЗП = ТекстЗП +"
	|FROM $Регистр."+ИндРег+" AS TabR WITH (NOLOCK)
	|WHERE
	|	TabR.IDDOC = '" + глMDW.ЗначениеВСтрокуБД(Док.ТекущийДокумент()) + "'
	|ORDER BY
	|	ID";
	ТЗВозв = глВыполнитьЗапросSQL(ТекстЗП);
	Возврат(ТЗВозв);
КонецФункции
 

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