При получении остатков или оборотов из регистра бухгалтерии разработчики часто сталкиваются с задачей: выбрать данные не по одному конкретному счету, а по списку счетов или по группам субсчетов (например, отобрать счета 21, 43 и группу субсчетов счета 10: 10.01–10.09). Проанализируем, как правильно составить такой запрос, как передать параметры и как оптимизировать производительность выборки.
Разберем классический и наиболее гибкий способ. Чтобы выбрать счета вместе со всеми их подчиненными субсчетами (например, счет 10 со всеми его субсчетами от 10.01 до 10.09), в языке запросов 1С используется конструкция В ИЕРАРХИИ. В нее можно передавать как одиночное значение, так и коллекцию значений (массив или список значений).
Для правильного выполнения запроса и высокой скорости работы условия отбора по счетам следует помещать не в секцию ГДЕ, а во второй параметр виртуальной таблицы Остатки (параметр УсловиеСчета).
Посмотрим на пример формирования массива счетов и текста запроса:
// Формируем список счетов для отбора
СписокСчетов = Новый Массив;
СписокСчетов.Добавить(ПланыСчетов.Хозрасчетный.ПолуфабрикатыСобственногоПроизводства); // Счет 21
СписокСчетов.Добавить(ПланыСчетов.Хозрасчетный.Материалы); // Счет 10 (будут выбраны все субсчета)
СписокСчетов.Добавить(ПланыСчетов.Хозрасчетный.ГотоваяПродукция); // Счет 43
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстатки.Счет КАК Счет,
| ХозрасчетныйОстатки.Субконто1 КАК Субконто1,
| ХозрасчетныйОстатки.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(
| &Период,
| Счет В ИЕРАРХИИ (&СписокСчетов),
| ,
| КоличествоОстаток > 0) КАК ХозрасчетныйОстатки";
Запрос.УстановитьПараметр("Период", ТекущаяДата());
Запрос.УстановитьПараметр("СписокСчетов", СписокСчетов);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Обработка полученных данных
КонецЦикла;
Рассмотрим ситуацию, когда список счетов строго фиксирован и не зависит от выбора пользователя в пользовательском интерфейсе. В этом случае нет необходимости создавать коллекцию в коде встроенного языка и вызывать метод УстановитьПараметр. Можно указать предопределенные счета непосредственно в тексте запроса с помощью функции ЗНАЧЕНИЕ.
Посмотрим, как выглядит текст такого запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстатки.Счет КАК Счет,
| ХозрасчетныйОстатки.Субконто1 КАК Субконто1,
| ХозрасчетныйОстатки.КоличествоОстаток КАК КоличествоОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(
| &Период,
| Счет В ИЕРАРХИИ (
| ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ПолуфабрикатыСобственногоПроизводства),
| ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Материалы),
| ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ГотоваяПродукция)
| ),
| ,
| КоличествоОстаток > 0) КАК ХозрасчетныйОстатки";
Запрос.УстановитьПараметр("Период", ТекущаяДата());
РезультатЗапроса = Запрос.Выполнить();
Выясним ключевые нюансы, на которые необходимо обращать внимание при работе с запросами к регистру бухгалтерии:
ГДЕ, платформа сначала рассчитает остатки по всей таблице регистра и лишь затем отфильтрует результат, что приведет к существенному падению производительности.Счет В (&СписокСчетов) производит точное сопоставление. Если передать счет 10, субсчета 10.01 или 10.02 в выборку не попадут. Для захвата всех вложенных субсчетов обязательно используйте Счет В ИЕРАРХИИ (&СписокСчетов).&СписокСчетов передать пустой массив или пустой список значений, условие вернет ложь (1 = 0), и запрос вернет пустую таблицу. Перед выполнением запроса проверяйте заполненность коллекции.Субконто1 обращается к первому субконто счета. Если у счетов 10, 21 и 43 порядок видов субконто различается, поле Субконто1 вернет разные типы значений. Для жесткой фиксации состава субконто передавайте необходимый массив видов субконто в 3-й параметр виртуальной таблицы (Субконто).