Имя: Пароль:
1C
1С v8
кто делал списание по ФИФО прямо в запросе?
0 vde69
 
модератор
28.10.13
16:32
решил сделать прямо в запросе, чую можно но что-то муторное.

кто делал? поделитесь :)
1 Ненавижу 1С
 
гуру
28.10.13
16:33
2 Господин ПЖ
 
28.10.13
16:34
все делали имхо... кто к экзамену по платформе готовился
3 NcSteel
 
28.10.13
16:35
(0) ИМХО, но глупость это ФИФО в запросах.
4 Wobland
 
28.10.13
16:37
(2) я не делал. сразу, ибо муторно и нафих не надо
5 scanduta
 
28.10.13
16:40
А в чем сложность то?
6 Новиков
 
28.10.13
16:40
(0) не, Дим. Не делай. Овчинка выделки не стоит. В цикле закрыть для средне-статистического документа с проверкой хватает/не хватает получается быстрее по дереву, нежели нужные колличества получать переджойнами.

Для маленьких, теория: http://infostart.ru/public/99207/
7 kumena
 
28.10.13
16:52
"все делали имхо... кто к экзамену по платформе готовился"

там только выборка данных в запросе
8 kumena
 
28.10.13
16:53
смысл запроса быстро вытаскивать данные из базы за один раз.
смысла делать вычисления прямо тем же запросом по моему нет.
9 vde69
 
модератор
28.10.13
17:00
нарастающий итог я сделал давно, здесь проблема как отделить часть данных

например надо списать 250р, строим времянку:
сумма, дата - нарастающий итог
+100  1.1.1 - 100
+200  2.1.1 - 300
-100  3.1.1 - 200
-100  4.1.1 - 100

по алгоритму (1) я получу
1.1.1 - 100
2.1.1 - 200
3.1.1 - 200
4.1.1 - 100

что не правильно я должен получить
1.1.1 - 100
2.1.1 - 200

то есть у меня проблемы с тем что бы в результат не попадали лишние строки
10 Ненавижу 1С
 
гуру
29.10.13
09:59
(9) вообще-то строится отдельно нарастающий итог по приходу и отдельно по расходу и затем определяются несписанные партии, в (1) сильно упрощенный вариант
11 GANR
 
29.10.13
10:14
(0) Можно это сделать, но не нужно. (2) Я готовился, но мне в голову не приходило делать это в запросе - нарастающий итог там надо считать, а в 1С-запросе это будет очень и очень ресурсоемкой операцией, да и запрос может быть очень непростым.

А вот в MS SQL 2012 с его специально заточенными под подобные задачи оконными функциями решать такие задачи - одно удовольствие http://www.sql-tutorial.ru/ru/book_running_totals.html.
12 GANR
 
29.10.13
10:17
+(11) Не факт, конечно, что в МС СКЛ 2012 это будет работать быстрее и менее ресурсоемко, но запрос написать стало существенно проще.
13 vvf1973
 
29.10.13
10:34
(9) интересно, а нарастающие итоги вы случайно не запросом делали? :-)
а так http://nashe1c.ru/materials-view.jsp?id=312 :-)
14 vde69
 
модератор
29.10.13
10:39
в результате я отказался от идеи, все равно пришлось кое чего считать в 1с, как всегда истина где-то посередине...
15 Sorm
 
29.10.13
11:02
(11) Коррелированные подзапросы, конечно, красиво, но долго.
16 MadHead
 
29.10.13
11:11
Нарастающий итог в запросе еще то зло. Списание не рискнул бы делать в реальных задачах. А в отчетах иногда применяю
17 GANR
 
29.10.13
11:23
(15) Да нарастающий итог в запросе как ни делай - хоть коррелированный подзапрос, хоть с соединениями заморочиться (единственный вариант для 1С) - все равно ресурсоемко и долго будет, только оконные функции МС СКЛ 2012 могут сделать запрос более-менее нормальным.
18 Serginio1
 
29.10.13
12:03
(17) Если закинуть во внешнюю таблицу и проиндексировать то будет быстро. v8: Подзапросы с Выбрать Первые
19 GANR
 
29.10.13
12:34
(18) Ну да, индексы, конечно, ускорят процесс... Но даже если это будет и быстро, то сколько же оперативной памяти может сожрать ЭВМ, чтобы рассчитать все это безобразие в запросе, да и гибкость такого запроса будет никакая - лучше уж код. Там ведь надо каждую партию соединить со всеми партиями, поступившими раньше ее самой.
20 PR
 
29.10.13
12:36
(0) У меня только один вопрос. Нахрена?
21 Лодырь
 
29.10.13
12:43
(20)
1. Не надо писать гору ручного кода и обработка списания выглядит красиво.
2. Развлечение в стиле "а можно ли вырезать апендицит автогеном через задницу"
3. А вдруг будет работать быстрее?
4. Если могу, почему бы и нет?
22 Serginio1
 
29.10.13
18:41
(19) Достали эти деревья, там где нужно сделать итоги по группе полей. Помню замучился и написал униврсальную процедуру списания

Функция ПолучитьТзСписаний(Тз,Регистр,КолонкаСписываемогоКоличества,КолонкаКоличества,КолонкиСумм,отказ,СтрокиДляСортировки="") Экспорт
МассивИзмерений=новый Массив;
Колонки=Тз.Колонки;
Для каждого стр из Колонки Цикл
    Если (стр.Имя<>"ТзПоГруппе") и (стр.Имя<>КолонкаСписываемогоКоличества) Тогда
        МассивИзмерений.Добавить(Стр.Имя)
    КонецЕсли;    
КонецЦикла;

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

    Для каждого стр из Тз Цикл
        ТзПоГруппе=стр.ТзПоГруппе;
        СписываемоеКоличество=ТзПоГруппе[0][КолонкаСписываемогоКоличества];
        Если СписываемоеКоличество>Стр[КолонкаКоличества] Тогда
            СтрСообщ=ИмяРег+" Для измерений ";
            Для каждого Измерение из МассивИзмерений Цикл
                СтрСообщ=СтрСообщ+" "+Измерение+"="+Стр[Измерение]
            КонецЦикла;
            СтрСообщ=СтрСообщ+"
            |Остаток "+КолонкаКоличества+"="+Стр[КолонкаКоличества]+"<"+СписываемоеКоличество+" в накладной";
            Сообщить(СтрСообщ);
            отказ=истина;
            //продолжить
            СписываемоеКоличество=Стр[КолонкаКоличества];
        КонецЕсли;    
        
        Если не ПустаяСтрока(СтрокиДляСортировки)  Тогда
   ТзПоГруппе.Сортировать(СтрокиДляСортировки,Сравнение);
КонецЕсли;
      ЗаполнитьТзСписания(ТзПоГруппе,Резулт,СписываемоеКоличество,КолонкаКоличества,МассивКолонокСумм);
      Если СписываемоеКоличество>0 Тогда
        СтрСообщ="Для измерений ";
            Для каждого Измерение из МассивИзмерений Цикл
                СтрСообщ=СтрСообщ+" "+Измерение+"="+Стр[Измерение]
            КонецЦикла;
            СтрСообщ=СтрСообщ+"
            |не списано "+СписываемоеКоличество;
            Сообщить(СтрСообщ);
    КонецЕсли;
  КонецЦикла;
  
    
  возврат Резулт
КонецФункции



и пример использования

Рез=акСмешанный.глСгруппироватьТзПоПолям(Запрос.Выполнить().выгрузить(),"Номенклатура,ХарактеристикаНоменклатуры","Количество");
ТзРезулт=акСмешанный.ПолучитьТзСписаний(рез,РегистрыНакопления.акПродажи,"КоличествоСписания","Количество","СебеСтоимостьUSD,СебеСтоимостьRUR",Отказ);
23 Serginio1
 
29.10.13
18:45
Процедура ЗаполнитьТзСписания(Тз,ТзСписания,СписываемоеКоличество,КолонкаКоличества,КолонкиСумм)
    Если СписываемоеКоличество=0 Тогда
        возврат
    КонецЕсли;    
    Для каждого Стр из Тз Цикл
        
        КоличествоПоСтроке=Стр[КолонкаКоличества];
        Если КоличествоПоСтроке<=0 Тогда
            продолжить
        КонецЕсли;    
        СтрТз=ТзСписания.Добавить();
        ЗаполнитьЗначенияСвойств(СтрТз,Стр);
        Если СписываемоеКоличество>=КоличествоПоСтроке Тогда
            СписываемоеКоличество=СписываемоеКоличество-КоличествоПоСтроке;
        Иначе
            СтрТз[КолонкаКоличества]=СписываемоеКоличество;
            Если  КоличествоПоСтроке<>0 Тогда
                Коэф=СписываемоеКоличество/КоличествоПоСтроке;
                Для каждого Колонка из КолонкиСумм Цикл
                    СтрТз[Колонка] =Стр[Колонка]*Коэф
                КонецЦикла;
            КонецЕсли;
            
            СписываемоеКоличество=0;
            
        КонецЕсли;
        Если СписываемоеКоличество=0 Тогда
            возврат
        КонецЕсли;      
    КонецЦикла;    
    
        
КонецПроцедуры
24 Classic
 
29.10.13
18:48
Вот прям щас и делаю. ФИФО ж не только к товарным движениям относится?
25 1Cv8_accepted
 
29.10.13
18:49
(0) АВТОУПОРЯДОЧИВАНИЕ
26 Classic
 
29.10.13
18:49
Самыйй жир считать начальный остаток
27 GROOVY
 
29.10.13
18:50
Народ, все в запросах сделать можно, но не нужно. Даже с точки зрения производительности. Я уж молчу про поиск ошибок и последующей адаптации.
28 1Cv8_accepted
 
29.10.13
18:51
(0) А вообще зависит от объёмов данных. Иной раз лучше и на клиенте сложение-вычитание сделать, чтобы дать серверу глоток для следующего ожидающего запроса. Но это - такой тооонкий момент...
29 1Cv8_accepted
 
29.10.13
18:52
(27) д!
30 kiruha
 
29.10.13
19:00
(21)
Все правильно кроме - быстрее будет работать
31 Serginio1
 
29.10.13
19:03
23+ Функция СравнитьПоля(Структ,Строка)
    Для каждого стр из Структ Цикл
        Если Стр.Значение<>Строка[Стр.Ключ] Тогда
            возврат ложь
        КонецЕсли;
    КонецЦикла;    
        возврат истина
    КонецФункции
    
    Процедура ДобавитьПоля(Тз,ТзОриг,Поля) Экспорт
        если ПустаяСтрока(Поля) Тогда
            возврат
        КонецЕсли;
        
        МассивПолей=ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(Поля,",");
        Для каждого Поле из МассивПолей Цикл
     Колонка=ТзОриг.Колонки.Найти(Поле);
     Тз.Колонки.Добавить(Колонка.Имя,Колонка.типЗначения);
     КонецЦикла;

КонецПроцедуры

Процедура ПроссумироватьПоля(Тз,ТзСтрок,МассивСуммируемыхПолей)
     Для Каждого Стр из МассивСуммируемыхПолей Цикл
        Тз[стр] = ТзСтрок.Итог(Стр);
     КонецЦикла;
    
КонецПроцедуры

Функция глСгруппироватьТзПоПолям(Тз,Поля,СуммируемыеПоля,ПоляСортировкиТзПоГруппе="") Экспорт
     перем Тип,Длина,Точность,ЕстьСпр,ЕстьДок;
     ЕстьСпр=0; ЕстьДок=0;
     //Тз.ПолучитьПараметрыКолонки(поле,тип,Длина,Точность);
     если ПустаяСтрока(СуммируемыеПоля) Тогда
         МассивСуммируемыхПолей=Новый массив;
         Иначе
     МассивСуммируемыхПолей=ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(СуммируемыеПоля,",");
     КонецЕсли;
     Структ=Новый Структура(Поля);
    
     // Для того что бы правильно сртировались элементы с одинаковыми представление
     // Сначала отсортируем по внутреннему значению
     //а после группирования по представлению по возрастанию
     Сравнение=Новый СравнениеЗначений;
   //  Тз.Сортировать(ПолучитьСтрокуСортПоля(Поле,Тз,ЕстьСпр,ЕстьДок));
  
   ПоляСортировки=Поля;
   Если не пустаяСтрока(ПоляСортировкиТзПоГруппе) Тогда
       ПоляСортировки=ПоляСортировки+","+ПоляСортировкиТзПоГруппе
   КонецЕсли;
   Тз.Сортировать(ПоляСортировки,Сравнение);
  
     ТзФ=новый ТаблицаЗначений;
      ДобавитьПоля(ТзФ,Тз,Поля);
      ДобавитьПоля(ТзФ,Тз,СуммируемыеПоля);
      
      ТзФ.Колонки.Добавить("ТзПоГруппе",Новый ОписаниеТипов("ТаблицаЗначений"));
      
     ТекСтр=0;
     Заявка=0;  
     НачСтр=-1;
     СтрТзф="";
     Если Тз.Количество()>0 Тогда
          
         Для сч=0 По Тз.Количество()-1 Цикл
             строка=тз[сч];
                            
               Если (Сч=0) или не СравнитьПоля(Структ,Строка) Тогда
                    Если НачСтр>-1 Тогда
                         ТекТз=Тз.Скопировать(ПолучитьМассивСтрок(Тз,НачСтр,сч-1));
                         СтрТзф.ТзПоГруппе=ТекТз;
                         ПроссумироватьПоля(СтрТзф,ТекТз,МассивСуммируемыхПолей);
                    КонецЕсли;
                    
                   СтрТзф= ТзФ.Добавить();
                   Для каждого стр из Структ Цикл
                     Поле=Стр.Ключ;
                     Значение=Строка[поле];
                     Структ[Поле]=Значение;
                     СтрТзф[Поле]=Значение;
                  
                   КонецЦикла;
                    
                    НачСтр=сч;
               КонецЕсли;    
               // глКлонироватьЗапись(Тз,сч,ТекТз)
          КонецЦикла;
          
          Если НачСтр>-1 Тогда
               ТекТз=Тз.Скопировать(ПолучитьМассивСтрок(Тз,НачСтр,Тз.Количество()-1));
               СтрТзф.ТзПоГруппе=ТекТз;
               ПроссумироватьПоля(СтрТзф,ТекТз,МассивСуммируемыхПолей);
          КонецЕсли;
     КонецЕсли;
          Возврат ТзФ;
КонецФункции
32 КонецЦикла
 
29.10.13
19:06
(11) Нарастающий итог уже давным давно считают одним простым запросом (по нужным полям)
33 Serginio1
 
29.10.13
19:09
Запрос=Новый Запрос;
    Запрос.Текст="ВЫБРАТЬ
    |    Таблица.Номенклатура КАК Номенклатура,
    |    Таблица.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    |    Таблица.Количество КАК Количество,
    |    Таблица.ПродажаRUR КАК ПродажаRUR,
    |    Таблица.ПродажаUSD КАК ПродажаUSD,
    |    Таблица.НомерСтроки КАК НомерСтроки
    |ПОМЕСТИТЬ Таблица
    |ИЗ
    |    &Тз КАК Таблица
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    Таблица.Номенклатура КАК Номенклатура,
    |    Таблица.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
    |    акПродажиОстатки.ДокументОприходования КАК ДокументОприходования,
    |    Таблица.Количество КАК КоличествоСписания,
    |    Таблица.ПродажаRUR КАК ПродажаRUR,
    |    Таблица.ПродажаUSD КАК ПродажаUSD,
    |    акПродажиОстатки.СебеСтоимостьUSDОстаток КАК СебеСтоимостьUSD,
    |    акПродажиОстатки.СебеСтоимостьRURОстаток КАК СебеСтоимостьRUR,
    |    акПродажиОстатки.КоличествоОстаток КАК Количество,
    |    акПродажиОстатки.ДокументОприходования.Контрагент КАК Поставщик,
    |    акПродажиОстатки.ХарактеристикаНоменклатуры.Прайс КАК Прайс,
    |    Таблица.НомерСтроки КАК НомерСтроки
    |ИЗ
    |    Таблица КАК Таблица
    |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.акПродажи.Остатки(
    |                ,
    |                (Номенклатура, ХарактеристикаНоменклатуры) В
    |                    (ВЫБРАТЬ
    |                        тз.Номенклатура,
    |                        тз.ХарактеристикаНоменклатуры
    |                    ИЗ
    |                        Таблица КАК тз)) КАК акПродажиОстатки
    |        ПО Таблица.Номенклатура = акПродажиОстатки.Номенклатура
    |            И Таблица.ХарактеристикаНоменклатуры = акПродажиОстатки.ХарактеристикаНоменклатуры
    |
    |УПОРЯДОЧИТЬ ПО
    |    НомерСтроки";
    Запрос.УстановитьПараметр("Тз",Тз);
    Рез=акСмешанный.глСгруппироватьТзПоПолям(Запрос.Выполнить().выгрузить(),"Номенклатура,ХарактеристикаНоменклатуры","Количество");
    
    Отказ=ложь;
    ТзРезулт=акСмешанный.ПолучитьТзСписаний(рез,РегистрыНакопления.акПродажи,"КоличествоСписания","Количество","СебеСтоимостьUSD,СебеСтоимостьRUR",Отказ);
34 GANR
 
29.10.13
19:16
(22) Полезная вещь во многих случаях.
Я не хочу быть самым богатым человеком на кладбище. Засыпать с чувством, что за день я сделал какую-нибудь потрясающую вещь — вот что меня интересует. Стив Джобс