1C-Code → Как сделать → Как получить остатки на дату запросом в 1С
Из виртуальной таблицы Остатки регистра накопления, передав дату параметром в скобках после имени таблицы. Никаких циклов и никакого перебора движений.
ВЫБРАТЬ
Остатки.Номенклатура,
Остатки.Склад,
Остатки.КоличествоОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&НаДату, ) КАК Остатки
Это главное. Остатки(&НаДату, ) заставляет платформу посчитать остаток на момент — она возьмёт ближайший рассчитанный итог и доведёт его движениями. Условие ГДЕ Период <= &НаДату так не работает: оно отфильтрует строки уже посчитанной таблицы, а не изменит расчёт.
Пустое место после запятой означает «по всему регистру». Если нужны остатки по одному складу, пишите Остатки(&НаДату, Склад = &Склад). Отбор ВНУТРИ скобок отсекает данные до расчёта, а тот же отбор в ГДЕ — после: разница на большой базе в разы.
Дата без времени — это полночь, то есть НАЧАЛО дня. Остатки «на 31 января» почти всегда означают «на конец 31 января», иначе весь день выпадает. Передавайте КонецДня(Дата).
Товара, по которому движений не было, в результате не будет вовсе. Если нужны все позиции номенклатуры, соединяйте справочник с остатками ЛЕВЫМ соединением и оборачивайте количество в ЕСТЬNULL(Остатки.КоличествоОстаток, 0).
Самая дорогая ошибка здесь — запрос в цикле: пройти по строкам документа и для каждой спросить остаток. На десяти строках незаметно, на тысяче — минуты и блокировки. Остатки берут ОДНИМ запросом сразу по всем нужным позициям, передав их списком в параметр.
Задача на это. Прочитать приём и применить его — разные умения. В тренажёре есть задача «Остатки по складу для всех товаров»: получить остатки так, чтобы в результат попали и позиции без движений — с нулём, а не пропали из отчёта. Решение проверяется скрытыми тестами, в том числе на краевых случаях, о которых в условии не сказано.