Имя: Пароль:
1C
1С v8
1c 8 как из регистра накопления выбрать первые записи дающие итог больше чем Х
,
0 kvrkvr
 
16.04.13
16:58
Как из регистра накопления выбрать первые записи дающие итог больше или равно чем определённое значение?
Задача получить последние движения регистра партии с итогом больще или равно чем N. Или надо в цикле повторять запрос?
1 zladenuw
 
16.04.13
17:13
вложенный запрос с твоим условием
2 Classic
 
16.04.13
17:14
ИМЕЮЩИЕ
3 kvrkvr
 
16.04.13
19:01
А чуть подробнее?

Типовое отраслевое решение
"Альфа-Авто: Автосервис+Автозапчасти, украинская версия 4.1"
Разработка: "1С-Рарус" Локализация: "АБИ Украина" (4.1.07.01)

Это корректировка проведения документа "ЗакрытиеСмены", корректируестя набор записей регистра Партии. Документ - это свёртка чеков за день. Возвраты собираются в отдельный документ. Если есть остаток на какой - либо партии, то на нё и возвращается (на последнюю). А вот если нет, тогда возвращается на специальный документ прихода, задаётся константой. Называется партия нулевых остатков.
Требуется выбрать в обратном порядке меньше момента времени текущего документа движения чтобы рапределить движение возврата на партии по которым продавалось через кассу.

Вот код из модуля:

В обработке проведения вызов, после формирования набора записей:

   // проведем партии товаров
   Отказ=НЕ ПровестиПоПартиям(Режим,Ссылка) ИЛИ Отказ;
   // --> + Рубцов в конфу Начало, откорректируем Проведение по партиям, распределим партию отрицательных остатков на продажи по Другим закрытиям кассовой смены
   Если ЭтотОбъект.СуммаДокумента < 0 Тогда
       ОткорректируемПроведениеПоПартиям(Отказ);
   КонецЕсли;    
   // --> - Рубцов в конфу Конец, откорректируем Проведение по партиям, распределим партию отрицательных остатков на продажи по Другим закрытиям кассовой смены    

Ну и сама процедура:

// --> + Рубцов в конфу Начало, откорректируем Проведение по партиям, распределим партию отрицательных остатков на продажи по Другим закрытиям кассовой смены
Процедура ОткорректируемПроведениеПоПартиям(Отказ)
       //    НЗНов = РегистрыНакопления.ПартииТоваровКомпании.СоздатьтекНЗПартии();
       текНЗПартии = ЭтотОбъект.Движения.ПартииТоваровКомпании;
       Если текНЗПартии.Количество() = 0 Тогда
           Возврат;
       КонецЕсли;    
       ПартНулОст = Константы.ПартияТоваровОтрицательныхОстатков.Получить();
       ТЗЗап = текНЗПартии.Выгрузить();
       МасСтрокНеПартНулОст = Новый Массив;
       МасСтрокПартНулОст = Новый Массив;
       Для Каждого ТекСтрТЗЗап Из ТЗЗап Цикл
           Если ТекСтрТЗЗап.Партия = ПартНулОст Тогда
               МасСтрокПартНулОст.Добавить(ТекСтрТЗЗап);
           Иначе
               МасСтрокНеПартНулОст.Добавить(ТекСтрТЗЗап);
           КонецЕсли;                            
       КонецЦикла;
       ТЗЗапНов = ТЗЗап.Скопировать(МасСтрокНеПартНулОст);
       ТЗЗапНулОст = ТЗЗап.Скопировать(МасСтрокПартНулОст);
       //    ФункРубц.ПечатьТЗ(ТЗЗапНулОст, "ТЗЗапНулОст");
       Для Каждого тсТЗЗапНулОст Из ТЗЗапНулОст Цикл
           ОбработкаПрерыванияПользователя();
           ТекКВоРаспределить = - тсТЗЗапНулОст.Количество;    
           //    НачМомВрем = ТекущаяДата();
           //    Для ии = 1 По 5000 Цикл
           ЗапрРубц = Новый Запрос;
           ЗапрРубц.Текст = "ВЫБРАТЬ
           //|    ПартииТоваровКомпании.МоментВремени КАК МоментВремени,
           //|    ПартииТоваровКомпании.Регистратор,
           |    ПартииТоваровКомпании.Партия,
           |    ПартииТоваровКомпании.Количество,
           |    ПартииТоваровКомпании.СуммаУпр
           //        |    ПартииТоваровКомпании.ВидДвижения
           |ИЗ
           |    РегистрНакопления.ПартииТоваровКомпании КАК ПартииТоваровКомпании
           |ГДЕ
           |    ПартииТоваровКомпании.Период <= &КонДата
           |    И ПартииТоваровКомпании.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
           |    И ПартииТоваровКомпании.Регистратор ССЫЛКА Документ.ЗакрытиеСмены
           |    И ПартииТоваровКомпании.Номенклатура = &Номенклатура
           |    И ПартииТоваровКомпании.Количество > 0
           |
           |УПОРЯДОЧИТЬ ПО
           |    МоментВремени УБЫВ";
           
           //    ЗапрРубц.УстановитьПараметр("НачДата",'20000101');
           ЗапрРубц.УстановитьПараметр("КонДата",КонецДня(ЭтотОбъект.Дата));
           ЗапрРубц.УстановитьПараметр("Номенклатура",тсТЗЗапНулОст.Номенклатура);
           ВыбРубц = ЗапрРубц.Выполнить().Выбрать();
           Пока ВыбРубц.Следующий() Цикл
               ОбработкаПрерыванияПользователя();
               Если ТекКВоРаспределить <= 0 Тогда
                   прервать;
               КонецЕсли;
               тсТЗЗапНов = ТЗЗапНов.Добавить();
               ЗаполнитьЗначенияСвойств(тсТЗЗапНов, тсТЗЗапНулОст);
               КвоЗап = Мин(ТекКВоРаспределить,ВыбРубц.Количество);
               ТекКВоРаспределить = ТекКВоРаспределить - КвоЗап;
               СумЗап = КвоЗап*ВыбРубц.СуммаУпр/ВыбРубц.Количество;
               тсТЗЗапНов.Партия = ВыбРубц.Партия;
               тсТЗЗапНов.Количество = -КвоЗап;
               тсТЗЗапНов.Сумма = -СумЗап;
               тсТЗЗапНов.СуммаУпр = -СумЗап;
               тсТЗЗапНов.СуммаНДС = -СумЗап/6;            
           КонецЦикла;
           Если ТекКВоРаспределить > 0 Тогда
               Сообщить("Попытка вернуть "+тсТЗЗапНулОст.Номенклатура+" больше чем их было вообще продано!",СтатусСообщения.ОченьВажное);
               Отказ = Истина;
               возврат;
               тсТЗЗапНов = ТЗЗапНов.Добавить();
               ЗаполнитьЗначенияСвойств(тсТЗЗапНов, тсТЗЗапНулОст);
               тсТЗЗапНов.Количество = -ТекКВоРаспределить;            
           КонецЕсли;
       КонецЦикла;
       //    ФункРубц.ПечатьТЗ(ТЗЗапНов, "ТЗЗапНов");
       текНЗПартии.Загрузить(ТЗЗапНов);
       текНЗПартии.ОбменДанными.Загрузка = Истина;
       текНЗПартии.Записать();
КонецПроцедуры
// --> - Рубцов в конфу Конец , откорректируем Проведение по партиям, распределим партию отрицательных остатков на продажи по Другим закрытиям кассовой смены
4 Rovan
 
гуру
16.04.13
21:09
(+2) ПЕРВЫЕ... УПОРЯДОЧИТЬ ПО
5 mistеr
 
16.04.13
21:14
(0) Надо в цикле обходить выборку и считать итог.

Или на СКД сделать, она умеет считать сумму с накоплением.
6 milan
 
16.04.13
21:25
(5) а потом как советуют специалисты - первые и упорядочить по
7 mistеr
 
16.04.13
21:31
(6) Зачем еще "потом"? Сразу нельзя?
8 kvrkvr
 
17.04.13
10:47
Я чего - то не понимаю? Это не отчет, как делать на СКД? Это происходит при проведении документа. То есть СКД задать програмно? Ладно всем спасибо, идею я понял, но меня и так утсроит, у меня обычно не так много продаж по одному товару (супермаркет запчастей, инструмента для авто и т.п.), запускал в цикле запрос по несколько тысяч раз, разница когда все продажи получаю или только первую запись на 10%. Да и спрошу директора, по идее возвраты возможны только по продажам за последние 2 недели.
9 Лирик
 
17.04.13
10:54
(8) Покажу принцип, с условиями связи разберешься. Работает 100% делал 100 раз
ВЫБРАТЬ
   ДвиженияДенежныхСредств.Сумма,
   СУММА(ЕСТЬNULL(ДвиженияДенежныхСредств1.Сумма, 0)) КАК СуммаНакопления,
   ДвиженияДенежныхСредств.Регистратор
ИЗ
   РегистрНакопления.ДвиженияДенежныхСредств КАК ДвиженияДенежныхСредств
       ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ДвиженияДенежныхСредств КАК ДвиженияДенежныхСредств1
       ПО ДвиженияДенежныхСредств.Период < ДвиженияДенежныхСредств1.Период
ГДЕ
   ЕСТЬNULL(ДвиженияДенежныхСредств1.Сумма, 0) <= &НужнаяСумма

СГРУППИРОВАТЬ ПО
   ДвиженияДенежныхСредств.Регистратор,
   ДвиженияДенежныхСредств.Сумма
10 mistеr
 
17.04.13
11:30
(8) >запускал в цикле запрос по несколько тысяч раз
Значит, идею не понял.
11 kvrkvr
 
17.04.13
14:36
Лирику  - спасибо! Да, это то, что надо. Хотя у меня реально быстрее работает просто выборка последних за полгода, но это вероятно потому, что продаж по одной номенклатуре не так уж и много.
12 kvrkvr
 
17.04.13
14:41
В общем Лирику спасибо ещё раз, тему можно закрывать. Честно говоря даже как-то забыл, что возможно условие связи со знаком " < "!
Ошибка? Это не ошибка, это системная функция.