Как правильно получить остатки по счету 002 в запросе 1С

Программист 1С v8.3 (Обычные формы) Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок в 1С часто возникает задача получения остатков по конкретному счету бухгалтерского учета (например, по забалансовому счету 002 «Товарно-материальные ценности, принятые на ответственное хранение»). Нередко разработчики сталкиваются с ситуацией, когда запрос к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.Остатки не возвращает строк. Разберем основные причины такого поведения и способы их устранения.

Причина 1. Некорректное сравнение поля «Счет» со строкой

Поле Счет в таблицах регистра бухгалтерии имеет ссылочный тип данных (ссылка на элемент плана счетов). Если в параметрах виртуальной таблицы написать выражение вида Счет = "002", платформа будет сравнивать объектную ссылку со строковым литералом. Так как типы данных не совпадают, условие всегда возвращает ЛОЖЬ, и запрос возвращает пустой результат.

Рассмотрим правильные варианты фильтрации по счету плана счетов:

  1. Передача ссылки через параметр запроса (рекомендуемый способ):
    
    Запрос.Текст = 
    "ВЫБРАТЬ
    |   ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
    |   ХозрасчетныйОстатки.КоличествоОстатокДт КАК Количество,
    |   ХозрасчетныйОстатки.СуммаОстатокДт КАК Сумма
    |ИЗ
    |   РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, Счет = &Счет002, , Организация = &Организация) КАК ХозрасчетныйОстатки";
    
    Запрос.УстановитьПараметр("Счет002", ПланыСчетов.Хозрасчетный.НайтиПоКоду("002"));
    Запрос.УстановитьПараметр("ДатаОстатков", КонецДня(ТекущаяДата()));
    Запрос.УстановитьПараметр("Организация", ВыбОрганизация);
    
  2. Использование предопределенного значения в тексте запроса:
    
    РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, Счет = ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ТМЦпринятыеНаОтветственноеХранение), , Организация = &Организация)
    
  3. Фильтрация по реквизиту кода счета:
    
    РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, Счет.Код = "002", , Организация = &Организация)
    

    Обратите внимание: обращение через точку к реквизиту Счет.Код в условии виртуальной таблицы заставляет платформу выполнять дополнительное соединение, поэтому передача ссылки через параметр предпочтительнее с точки зрения производительности.

Причина 2. Ошибка в номере и назначении субконто

По умолчанию поля Субконто1, Субконто2, Субконто3 жестко соответствуют списку видов субконто, настроенному для конкретного счета в конфигураторе или в режиме «1С:Предприятие».

Например, для забалансового счета 002 в типовых конфигурациях (УПП, Комплексная автоматизация) порядок субконто выглядит следующим образом:

  1. Субконто1 — Контрагенты;
  2. Субконто2 — Номенклатура;
  3. Субконто3 — Склады (места хранения).

Если в условии наложить отбор на склад по полю Субконто2 (в котором фактически хранится номенклатура), условие Субконто2 В ИЕРАРХИИ(&Местонахождение) никогда не выполнится, так как ссылка на элемент справочника Склады не может находиться в иерархии элементов справочника Номенклатура.

Для исправления ситуации необходимо обращаться к нужному номеру субконто (для склада — Субконто3).

Рекомендации по оптимизации запроса к регистру бухгалтерии

Проанализируем типовые ошибки оптимизации и напишем корректный текст запроса:

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

Итоговый пример оптимизированного запроса

Посмотрим на пример законченного кода для получения остатков по счету 002:


Запрос = Новый Запрос;

// Задаем строгий порядок видов субконто
ВидыСубконто = Новый Массив;
ВидыСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура); // станет Субконто1
ВидыСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Склады);       // станет Субконто2

Запрос.Текст = 
"ВЫБРАТЬ
|   ВЫРАЗИТЬ(ХозрасчетныйОстатки.Субконто1 КАК Справочник.Номенклатура) КАК ТМЦ,
|   ВЫРАЗИТЬ(ХозрасчетныйОстатки.Субконто1 КАК Справочник.Номенклатура).Наименование КАК ТМЦНаименование,
|   ВЫРАЗИТЬ(ХозрасчетныйОстатки.Субконто2 КАК Справочник.Склады) КАК Склад,
|   ХозрасчетныйОстатки.КоличествоОстатокДт КАК КоличествоОстатокДт,
|   ХозрасчетныйОстатки.СуммаОстатокДт КАК СуммаОстатокДт
|ИЗ
|   РегистрБухгалтерии.Хозрасчетный.Остатки(
|       &ДатаОстатков,
|       Счет В ИЕРАРХИИ (&Счет002),
|       &ВидыСубконто,
|       Организация = &Организация
|           И Субконто2 В ИЕРАРХИИ (&Местонахождение)) КАК ХозрасчетныйОстатки
|
|УПОРЯДОЧИТЬ ПО
|   ТМЦНаименование";

Запрос.УстановитьПараметр("ДатаОстатков", Новый Граница(КонецДня(ДатаОстатков), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Счет002", ПланыСчетов.Хозрасчетный.НайтиПоКоду("002"));
Запрос.УстановитьПараметр("ВидыСубконто", ВидыСубконто);
Запрос.УстановитьПараметр("Организация", Организация);
Запрос.УстановитьПараметр("Местонахождение", Местонахождение);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Обработка полученных строк
КонецЦикла;
← На главную