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


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Помогите реализовать СводныйОстаток()
24. Января 2007 :: 09:12
Печать  
Лыжи не едут..
Помогите составить параметризированный прямой запрос к базе на скуле по сводным остаткам регистра остатков "Отгрузки" на точку актуальности.
Измерения регистра: Режим,Фирма,Автор,Склад,Контрагент,КредДокумент,Товар.
Ресурсы: Количество, Сумма

Есть фрагмент модуля 1С:

щийДокумент,,"Количество");
ТекущийДокумент,,"Количество");
Если (КоличествоСчет>0) и (КоличествоРасход=КоличествоСчет) Тогда
     Если Текст=0 Тогда
           Возврат 12;
     Иначе
           Возврат "Отгружено полностью";
     КонецЕсли;
ИначеЕсли (КоличествоСчет>0) и (КоличествоРасход>0) Тогда
     Если Текст=0 Тогда
           Возврат 9;
     Иначе
           Возврат "Отгружено "+глФРМ(КоличествоРасход,Константа.ЕдиницаПоУмолчанию,3);
     КонецЕсли;
ИначеЕсли (КоличествоСчет>0) и (КоличествоРасход=0) Тогда
     Если Текст=0 Тогда
           Возврат 7;
     Иначе
           Возврат "Не отгружено";
     КонецЕсли;
КонецЕсли;

Делаю так:

|SET NOCOUNT ON
|DECLARE @ТекДок CHAR(13)
|DECLARE @РежимСчет CHAR(9)
|DECLARE @РежимРасход CHAR(9)
|
|SET @ТекДок = ?
|SET @РежимСчет = ?
|SET @РежимРасход = ?
|SELECT
|      CASE
|            WHEN L1.P1>0 AND L1.P1=L2.P2 THEN 12
|            WHEN L1.P1>0 AND L2.P2>0 THEN 9
|            WHEN L1.P1>0 AND (L2.P2=0 or L2.P2 is null) THEN 7
|      ELSE 0
|      END,
|      CASE
|            WHEN L1.P1>0 AND L1.P1=L2.P2 THEN 'Отгружено полностью'
|            WHEN L1.P1>0 AND L2.P2>0 THEN 'Отгружено '+ CAST(L2.P2 AS varchar(16))
|            WHEN L1.P1>0 AND (L2.P2=0 or L2.P2 is null) THEN 'Не отгружен'
|      ELSE ''
|      END
|FROM (select ... as P1 from ...) as L1, (select ... as P2 from ...) as L2

Жалкие потуги на реализацию двух запросов в секции FROM к успеху не привели.
Помогите новичку, плз..
  
Наверх
ICQ  
IP записан
 
Славко
Senior Member
****
Отсутствует



Сообщений: 467
Местоположение: Украина, г. Днепропетровск
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #1 - 24. Января 2007 :: 10:13
Печать  
обрати внимание на ВТ $РегистрОстатки и не изобретай велосипед...
  

Ламер, самый обычный ламер...    сначала мы ...   а потом мы ...
Наверх
wwwICQ  
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #2 - 24. Января 2007 :: 13:55
Печать  
Делаю такой Фром:

(SELECT РегИтоги1.КоличествоОстаток as P1
FROM      $РегистрОстатки.Отгрузки(,,Режим = @РежимСчет AND КредДокумент = @Док,(Режим,КредДокумент),Количество) as РегИтоги1 (nolock)      ) AS L1,
(SELECT РегИтоги2.КоличествоОстаток as P2
FROM      $РегистрОстатки.Отгрузки(,,Режим = @РежимРасход AND КредДокумент = @Док,(Режим,КредДокумент),Количество) as РегИтоги2 (nolock)) AS L2

Ругается:
{E:\DB1C\TORG_20070112\EXTFORMS\ПРОБА\ПРОБА.ERT(14)}: State 42000, native 8158, message [Microsoft][ODBC SQL Server Driver][SQL Server]'РегИтоги1' has more columns than were specified in the column list
  
Наверх
ICQ  
IP записан
 
grayrat
Junior Member
**
Отсутствует



Сообщений: 99
Местоположение: Russia, Moscow
Зарегистрирован: 20. Мая 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #3 - 24. Января 2007 :: 14:25
Печать  
А поподробней, как у тебя регистр этот работает?
Когда счет выписывается - делается приход по измерению Режим=Счет, а когда списание - расход по измерению режим=Расход?
  
Наверх
 
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #4 - 24. Января 2007 :: 14:45
Печать  
Что-то вроде, но немного сложнее. У измерения Режим могут быть значения перечисления Счет, Приход, Расход, Заказ, ПриходСчет, СчетРасход, ЗаказСчет, ЗаказПриход. Двигается рег. Отгрузки, как правило, сразу по нескольким режимам.

А что, есть нюансы? Или неверен принцип получения сводного остатка как у меня выше?
Надо просто преобразовать 1С:
оличество") в параметризированный 1С++ запрос...
  
Наверх
ICQ  
IP записан
 
grayrat
Junior Member
**
Отсутствует



Сообщений: 99
Местоположение: Russia, Moscow
Зарегистрирован: 20. Мая 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #5 - 24. Января 2007 :: 15:09
Печать  
Т.е. у тебя по каждому измерению только в одну сторону движения бывают? Или как? Если Режим=Счет, к примеру, то остаток по всем когда либо выписаным счетам накапливается?
  
Наверх
 
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #6 - 24. Января 2007 :: 16:27
Печать  
Нет, движения по измерению Режим - в обе стороны. Если движение по конкретному документу(допустим счету), то он заносится в измерение КредДокумент. По завершению цепочки документов как правило остатки для цепочки обнуляются. Не всегда.
Это измерение Режим также имеется в нескольких других, участвующих в документообороте, регистрах...

Я не пойму, а что, способ использования измерения как-то влияет на архитектуру запроса и сводный остаток для одного измерения надо как-то по особому рассчитывать чем для какого-то другого?
  
Наверх
ICQ  
IP записан
 
grayrat
Junior Member
**
Отсутствует



Сообщений: 99
Местоположение: Russia, Moscow
Зарегистрирован: 20. Мая 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #7 - 24. Января 2007 :: 17:03
Печать  
Да нет, просто логику пытаюсь понять.
Сводный остаток у тебя будет получаться правильно.
Код
Выбрать все
(SELECT РегИтоги1.КоличествоОстаток as P1
FROM	$РегистрОстатки.Отгрузки(,,Режим = @РежимСчет AND КредДокумент = @Док,(Режим,КредДокумент),Количество) as РегИтоги1 (nolock)	) AS L1,
(SELECT РегИтоги2.КоличествоОстаток as P2
FROM	$РегистрОстатки.Отгрузки(,,Режим = @РежимРасход AND КредДокумент = @Док,(Режим,КредДокумент),Количество) as РегИтоги2 (nolock)) AS L2
 


(nolock) тут совершенно не к чему. ВТ и так с nolock-ом из таблиц читают
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: Помогите реализовать СводныйОстаток()
Ответ #8 - 25. Января 2007 :: 07:13
Печать  
Попробуй так:
Код
Выбрать все
Перем запрос;

Функция Расчет(ВозвратТекстом)
	запрос.УстПараметр(1, ТекущийДокумент, 1);
	Результат = запрос.ВыполнитьСкалярный();
	КоличествоСчет = Результат.КоличествоСчет;
	КоличествоРасход = Результат.КоличествоРасход;

	Если (КоличествоСчет>0) и (КоличествоРасход=КоличествоСчет) Тогда
		Возврат ?(ВозвратТекстом=0, 12, "Отгружено полностью");
	ИначеЕсли (КоличествоСчет>0) и (КоличествоРасход>0) Тогда
		Возврат ?(ВозвратТекстом=0, 9, "Отгружено "+глФРМ(КоличествоРасход,Константа.ЕдиницаПоУмолчанию,3));
	ИначеЕсли (КоличествоСчет>0) и (КоличествоРасход=0) Тогда
		Возврат ?(ВозвратТекстом=0, 7, "Не отгружено");
	КонецЕсли;

КонецФункции	// Расчет

Функция Подготовка()
	запрос = СоздатьОбъект("ODBCRecordSet");
	запрос.УстановитьТекстовыйПараметр("Счет", Перечисление.Режимы.Счет);
	запрос.УстановитьТекстовыйПараметр("Расход", Перечисление.Режимы.Расход);
	запрос.УстановитьТекстовыйПараметр("Период", запрос.мд.ПолучитьНачПериода());

	запрос.Подготовить("
	|select
	|sum(case when $Отгрузки.Режим = :Счет then $Отгрузки.Количество else 0 end) [КоличествоСчет],
	|sum(case when $Отгрузки.Режим = :Расход then $Отгрузки.Количество else 0 end) [КоличествоРасход]
	|from $РегистрИтоги.Отгрузки Отгрузки (nolock)
	|where Отгрузки.period = :Период~~
	|and $Отгрузки.КредДокумент = ?
	|and $Отгрузки.Режим in (:Расход, :Счет) -- хотя это можно и не добавлять, надо смотреть план запроса
	|");
	запрос.ДобПараметр(1, 14, 13, 0);
КонецФункции	// Подготовка

 


Имхо пытаться затащить в запрос помимо получения остатка еще и логику возврата значения не стоит, пусть каждый занимается своим делом - сервер выдает остаток, а 1С - что с ним делать.
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: Помогите реализовать СводныйОстаток()
Ответ #9 - 25. Января 2007 :: 07:22
Печать  
Да, надеюсь, по измерению КредДокумент стоит галка "Отбор итогов" ?
Иначе мимо всех индексов пролетаешь.
  
Наверх
 
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #10 - 25. Января 2007 :: 07:52
Печать  
Приблизительно так у меня сейчас и есть, только без прямых запросов...
В журнале документов "Счета" для трех колонок  с пиктограммами ("Оплата", "Отгрузка" и "Резерв") для каждого отображаемого документа шпарится 7 запросов по регистрам для вывода пиктограмм, да плюс еще эти же 7 для формирования строки состояния документа. Ессно, тормоза... Прошу сильно не ругать, - месяц как принял эту каличную базу...

Просто идея была уложить все 14 запросов по строке журнала в один параметризированный, для снятия тормозов при перемещении по журналу и снижения нагрузки на сервер...
  
Наверх
ICQ  
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: Помогите реализовать СводныйОстаток()
Ответ #11 - 25. Января 2007 :: 07:59
Печать  
Идея-то правильная.
Реализовать надо грамотно.
  
Наверх
 
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #12 - 25. Января 2007 :: 08:06
Печать  
Для грамотной реализации тямы не всегда хватает. Только месяц, как "подсел" на 1С++. Вот и задаю глупые вопросы, когда лбом упираюсь а ни в какую. Этот форум перечитал, ФАК и два талмуда по SQL заделались вместо библии, но без навыков и азов T-SQL пока бывает несколько проблематично решать очевидные для остальных вопросы. Спросить рядом не у кого, и, как следствие, мои темы на этом форуме, возможно заинтересующие только таких же ламеров ...  Смущённый
  
Наверх
ICQ  
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #13 - 25. Января 2007 :: 15:42
Печать  
[quote author=orefkov link=1169629950/0#8 date=1169709234]Попробуй так:
Код
Выбрать все
Функция Подготовка()
	запрос = СоздатьОбъект("ODBCRecordSet");
	запрос.УстановитьТекстовыйПараметр("Счет", Перечисление.Режимы.Счет);
	запрос.УстановитьТекстовыйПараметр("Расход", Перечисление.Режимы.Расход);
	запрос.УстановитьТекстовыйПараметр("Период", запрос.мд.ПолучитьНачПериода());

	запрос.Подготовить("
	|select
	|sum(case when $Отгрузки.Режим = :Счет then $Отгрузки.Количество else 0 end) [КоличествоСчет],
	|sum(case when $Отгрузки.Режим = :Расход then $Отгрузки.Количество else 0 end) [КоличествоРасход]
	|from $РегистрИтоги.Отгрузки Отгрузки (nolock)
	|where Отгрузки.period = :Период~~
	|and $Отгрузки.КредДокумент = ?
	|and $Отгрузки.Режим in (:Расход, :Счет) -- хотя это можно и не добавлять, надо смотреть план запроса
	|");
	запрос.ДобПараметр(1, 14, 13, 0);
КонецФункции	// Подготовка
 



Работает великолепно, почти на 5 баллов. Спасибо. Только...
А как сделать, чтобы сводный остаток правильно считался и для $Отгрузки.КредДокумент когда его дата меньше даты начала месяца точки актуальности? Если меньше, то врет...
  
Наверх
ICQ  
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: Помогите реализовать СводныйОстаток()
Ответ #14 - 26. Января 2007 :: 05:52
Печать  
Запрос выдает остатки на ТА, а не на дату КредДокумента.
  
Наверх
 
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #15 - 26. Января 2007 :: 11:15
Печать  
Прошу прощения, что усомнился... Действительно, всё правильно. Была ошибка в алгоритме обработки запроса
Спасибо!
  
Наверх
ICQ  
IP записан
 
Kapet
Senior Member
****
Отсутствует


Ламер - вансист

Сообщений: 262
Местоположение: Ukraine, Kyiv
Зарегистрирован: 27. Декабря 2006
Пол: Мужской
Re: Помогите реализовать СводныйОстаток()
Ответ #16 - 26. Января 2007 :: 15:13
Печать  
Извините, что напрягаю...

Фрагмент кода  получившегося работающего запроса:
Код
Выбрать все
|SET NOCOUNT ON
|DECLARE @Док CHAR(13)
|SET @Док = ?
|(
|SELECT
|	CASE
|		WHEN OPL.S1=0 AND OPL.S2>0 THEN 12
|		WHEN OPL.S1>0 AND OPL.S2>0 THEN 9
|		WHEN OPL.S1>0 AND OPL.S2=0 THEN 7
|	ELSE 0
|	END As ЗнакОплаты,
|	CASE
|		WHEN OPL.S1=0 AND OPL.S2>0 THEN 'Оплачен полностью'
|		WHEN OPL.S1>0 AND OPL.S2>0 THEN 'Оплачено '+ CAST(OPL.S2 AS varchar(16))
|		WHEN OPL.S1>0 AND OPL.S2=0 THEN 'Не оплачен'
|	ELSE 'Списан в доход'
|	END As СтрокаОплаты,
|	'_P1='+CAST(OPL.S1 AS varchar(16))+' _P2='+CAST(OPL.S2 AS varchar(16)),
|	CASE
|		WHEN OPL.S1=0 AND OPL.S2>0 THEN '"""+ШрифтЖирный+"""'
|		WHEN OPL.S1>0 AND OPL.S2>0 THEN '"""+ШрифтЖирный+"""'
|		WHEN OPL.S1>0 AND OPL.S2=0 THEN '"""+ШрифтЖирный+"""'
|	ELSE '"""+ШрифтОбычный+"""'
|	END As Шрифт
|FROM
|	(
|	SELECT
|		SUM($Оплаты.Сумма) as S1,
|		SUM($Оплаты.СуммаОплаты) as S2
|	FROM
|		$РегистрИтоги.Оплаты as Оплаты (nolock)
|	WHERE
|		Оплаты.period = :Период~~ AND
|		$Оплаты.КредДокумент = @Док
|	) AS OPL
|)
|UNION ALL
|( .......
 


Результат запроса обрабатывается так:

Функция Пиктограмма()
     ТД=ТекущийДокумент;
     Если ТД.Выбран()=0 Тогда
           МЧ_Оплата=0;
           МЧ_Отгрузка=0;
           МЧ_Резерв=0;
           ФонСтроки="NONE";
           СтатусОплаты="";
           СтатусОтгрузки="";
           Возврат "";
     КонецЕсли;
     _RS.УстПараметр(1,ТД);
     ТЗ=_RS.ВыполнитьИнструкцию();
     _МЧ_Оплата      =ТЗ.ПолучитьЗначение(1,1);
     _ФонСтроки      =ТЗ.ПолучитьЗначение(1,4);
     МЧ_Отгрузка      =ТЗ.ПолучитьЗначение(2,1);
     МЧ_Резерв      =ТЗ.ПолучитьЗначение(3,1);
     Если _МЧ_Оплата=0 Тогда
           Если (ТД.Проведен()=0) и (ТД.ПометкаУдаления()=0) Тогда
                 ФонСтроки=ШрифтОбычный;
                 МЧ_Оплата=_МЧ_Оплата;
                 Возврат "";
           ИначеЕсли ТД.Проведен()=1 Тогда
                 Док=СоздатьОбъект("Документ");
                 Док.ВыбратьПодчиненныеДокументы(,,ТД);
                 Пока Док.ПолучитьДокумент()=1 Цикл
                       Если (Док.Вид()="ОтменаСчета") и (Док.Проведен()=1) Тогда
                             ФонСтроки=ШрифтАннулирован;
                             МЧ_Оплата=_МЧ_Оплата;
                             Возврат "";
                       КонецЕсли;
                 КонецЦикла;
                 МЧ_Оплата=0;
                 ФонСтроки=ШрифтСписанВДоход;
                 Возврат "";
           ИначеЕсли ТД.ПометкаУдаления()=1 Тогда
                 МЧ_Оплата=0;
                 ФонСтроки=ШрифтПометкаУдаления;
                 Возврат "";
           КонецЕсли;
     КонецЕсли;
     МЧ_Оплата=_МЧ_Оплата;
     ФонСтроки=_ФонСтроки;
     Возврат "";
КонецФункции

Далее. Пытаюсь остаток алгоритма обработки запроса перепихнуть также в этот же запрос (сделать JOIN с самим документом @Док для получения его статуса "Проведен" и "Помечен На Удаление"и переложить всю работу на SQL).
Робкая неудачная попытка:
Код
Выбрать все
|SET NOCOUNT ON
|DECLARE @Док CHAR(13)
|SET @Док = ?
|(
|SELECT
|	CASE
|		WHEN OPL.S1=0 AND OPL.S2>0 THEN 12
|		WHEN OPL.S1>0 AND OPL.S2>0 THEN 9
|		WHEN OPL.S1>0 AND OPL.S2=0 THEN 7
|		WHEN (CL = 0 AND MK = 0) THEN 0 -- тут проблема
|	ELSE 0
|	END As ЗнакОплаты,
|	CASE
|		WHEN OPL.S1=0 AND OPL.S2>0 THEN 'Оплачен полностью'
|		WHEN OPL.S1>0 AND OPL.S2>0 THEN 'Оплачено '+ CAST(OPL.S2 AS varchar(16))
|		WHEN OPL.S1>0 AND OPL.S2=0 THEN 'Не оплачен'
|	ELSE 'Списан в доход'
|	END As СтрокаОплаты,
|	'_P1='+CAST(OPL.S1 AS varchar(16))+' _P2='+CAST(OPL.S2 AS varchar(16)),
|	CASE
|		WHEN OPL.S1=0 AND OPL.S2>0 THEN '"""+ШрифтЖирный+"""'
|		WHEN OPL.S1>0 AND OPL.S2>0 THEN '"""+ШрифтЖирный+"""'
|		WHEN OPL.S1>0 AND OPL.S2=0 THEN '"""+ШрифтЖирный+"""'
|	ELSE '"""+ШрифтОбычный+"""'
|	END As Шрифт
|FROM
|	(
|	SELECT
|		SUM($Оплаты.Сумма) as S1,
|		SUM($Оплаты.СуммаОплаты) as S2
|	FROM
|		$РегистрИтоги.Оплаты as Оплаты (nolock)
|	WHERE
|		Оплаты.period = :Период~~ AND
|		$Оплаты.КредДокумент = @Док
|	) AS OPL, (J.Closed & 1) AS CL, J.ISMARK AS MK -- наверное бред?
|INNER JOIN -- тут кажется тоже хрень
|	_1SJourn as J ON J.IDDoc = @Док
|)
 


и понимаю, что бык с курицей не скрещиваются. Подскажите, плз, как сделать правильно.
  
Наверх
ICQ  
IP записан
 
Переключение на Главную Страницу Страницы: [1] 
ОтправитьПечать