При разработке отчетов и обработок в 1С часто возникает задача получения остатков по конкретному счету бухгалтерского учета (например, по забалансовому счету 002 «Товарно-материальные ценности, принятые на ответственное хранение»). Нередко разработчики сталкиваются с ситуацией, когда запрос к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.Остатки не возвращает строк. Разберем основные причины такого поведения и способы их устранения.
Поле Счет в таблицах регистра бухгалтерии имеет ссылочный тип данных (ссылка на элемент плана счетов). Если в параметрах виртуальной таблицы написать выражение вида Счет = "002", платформа будет сравнивать объектную ссылку со строковым литералом. Так как типы данных не совпадают, условие всегда возвращает ЛОЖЬ, и запрос возвращает пустой результат.
Рассмотрим правильные варианты фильтрации по счету плана счетов:
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
| ХозрасчетныйОстатки.КоличествоОстатокДт КАК Количество,
| ХозрасчетныйОстатки.СуммаОстатокДт КАК Сумма
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, Счет = &Счет002, , Организация = &Организация) КАК ХозрасчетныйОстатки";
Запрос.УстановитьПараметр("Счет002", ПланыСчетов.Хозрасчетный.НайтиПоКоду("002"));
Запрос.УстановитьПараметр("ДатаОстатков", КонецДня(ТекущаяДата()));
Запрос.УстановитьПараметр("Организация", ВыбОрганизация);
РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ТМЦпринятыеНаОтветственноеХранение), , Организация = &Организация)
РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, Счет.Код = "002", , Организация = &Организация)
Обратите внимание: обращение через точку к реквизиту Счет.Код в условии виртуальной таблицы заставляет платформу выполнять дополнительное соединение, поэтому передача ссылки через параметр предпочтительнее с точки зрения производительности.
По умолчанию поля Субконто1, Субконто2, Субконто3 жестко соответствуют списку видов субконто, настроенному для конкретного счета в конфигураторе или в режиме «1С:Предприятие».
Например, для забалансового счета 002 в типовых конфигурациях (УПП, Комплексная автоматизация) порядок субконто выглядит следующим образом:
Субконто1 — Контрагенты;Субконто2 — Номенклатура;Субконто3 — Склады (места хранения).Если в условии наложить отбор на склад по полю Субконто2 (в котором фактически хранится номенклатура), условие Субконто2 В ИЕРАРХИИ(&Местонахождение) никогда не выполнится, так как ссылка на элемент справочника Склады не может находиться в иерархии элементов справочника Номенклатура.
Для исправления ситуации необходимо обращаться к нужному номеру субконто (для склада — Субконто3).
Проанализируем типовые ошибки оптимизации и напишем корректный текст запроса:
ГДЕ фильтрует данные уже после того, как виртуальная таблица рассчитает остатки по всем записям базы данных. Все отборы по измерениям и субконто необходимо указывать в 4-м параметре виртуальной таблицы Остатки.Субконто1, Субконто2 распределяются строго в порядке переданного массива.Остатки уже возвращает сгруппированные и просуммированные итоги. Конструкция СГРУППИРОВАТЬ ПО и функции СУММА() в данном случае создают избыточную нагрузку на СУБД.ВЫРАЗИТЬ(...).Посмотрим на пример законченного кода для получения остатков по счету 002:
Запрос = Новый Запрос;
// Задаем строгий порядок видов субконто
ВидыСубконто = Новый Массив;
ВидыСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура); // станет Субконто1
ВидыСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Склады); // станет Субконто2
Запрос.Текст =
"ВЫБРАТЬ
| ВЫРАЗИТЬ(ХозрасчетныйОстатки.Субконто1 КАК Справочник.Номенклатура) КАК ТМЦ,
| ВЫРАЗИТЬ(ХозрасчетныйОстатки.Субконто1 КАК Справочник.Номенклатура).Наименование КАК ТМЦНаименование,
| ВЫРАЗИТЬ(ХозрасчетныйОстатки.Субконто2 КАК Справочник.Склады) КАК Склад,
| ХозрасчетныйОстатки.КоличествоОстатокДт КАК КоличествоОстатокДт,
| ХозрасчетныйОстатки.СуммаОстатокДт КАК СуммаОстатокДт
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(
| &ДатаОстатков,
| Счет В ИЕРАРХИИ (&Счет002),
| &ВидыСубконто,
| Организация = &Организация
| И Субконто2 В ИЕРАРХИИ (&Местонахождение)) КАК ХозрасчетныйОстатки
|
|УПОРЯДОЧИТЬ ПО
| ТМЦНаименование";
Запрос.УстановитьПараметр("ДатаОстатков", Новый Граница(КонецДня(ДатаОстатков), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Счет002", ПланыСчетов.Хозрасчетный.НайтиПоКоду("002"));
Запрос.УстановитьПараметр("ВидыСубконто", ВидыСубконто);
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("Местонахождение", Местонахождение);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Обработка полученных строк
КонецЦикла;