При работе с бухгалтерскими запросами в системе 1С:Предприятие программисты часто сталкиваются с задачей выборки данных по определенному диапазону счетов. Например, когда необходимо получить обороты или остатки не по всему плану счетов, а только по группе (например, с 10 по 41 счет). На первый взгляд задача кажется простой, но она таит в себе множество нюансов, связанных с типами данных, иерархией и особенностями хранения планов счетов в базе данных.
В этой статье мы подробно разберем, как наиболее правильно и эффективно реализовать выборку диапазона счетов программно, проанализируем различные подходы и выясним, почему одни методы работают лучше других.
Самый очевидный способ, который приходит в голову начинающему разработчику, — это использование оператора МЕЖДУ для строкового реквизита Код. Рассмотрим, как это выглядит в тексте запроса:
Пример кода:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Хозрасчетный.Ссылка КАК Ссылка
|ИЗ
| ПланСчетов.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| Хозрасчетный.Код МЕЖДУ &НачКод И &КонКод";
Запрос.УстановитьПараметр("НачКод", "10");
Запрос.УстановитьПараметр("КонКод", "20");
Проанализируем этот подход. Основная проблема здесь заключается в строковом сравнении. В языке SQL (и, соответственно, в 1С) строки сравниваются посимвольно. Это означает, что если в вашем плане счетов есть счета с разной длиной кода или сложной структурой (с точками), результат может быть непредсказуемым. Например, счет "10.01" при строковом сравнении может оказаться "больше", чем счет "101", хотя логически в бухгалтерском учете он должен идти раньше. Поэтому использование прямого сравнения кодов считается небезопасной практикой, особенно в типовых конфигурациях со сложной иерархией.
Для решения проблем строковой сортировки в платформе 1С предусмотрен стандартный реквизит Порядок. Это скрытое индексированное поле, которое автоматически заполняется системой. В нем коды счетов преобразуются в специальный формат, который гарантирует правильную последовательность счетов с учетом их вложенности и точек в коде.
Рассмотрим, как правильно использовать этот реквизит в запросе. Для этого нам сначала нужно получить значения порядка для граничных счетов.
Пример реализации:
// Сначала получаем значения реквизита Порядок для наших ссылок
НачПорядок = СтрСчетОт.Порядок;
КонПорядок = СтрСчетДо.Порядок;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Хозрасчетный.Ссылка
|ИЗ
| ПланСчетов.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| Хозрасчетный.Порядок МЕЖДУ &НачПорядок И &КонПорядок";
Запрос.УстановитьПараметр("НачПорядок", НачПорядок);
Запрос.УстановитьПараметр("КонПорядок", КонПорядок);
Выясним причину, почему это лучше: поле Порядок всегда индексировано, что обеспечивает мгновенный поиск. Это наиболее надежный способ получить "физический" интервал счетов так, как они расположены в списке плана счетов.
Если вам заранее известен список счетов или вы выбираете их программно на основе каких-то условий, можно передать в запрос готовый массив ссылок. Это избавляет от необходимости вычислять диапазоны внутри самого запроса.
Разберем по шагам:
Массив.ПланыСчетов.Хозрасчетный.Товары).В.
МассивСчетов = Новый Массив;
МассивСчетов.Добавить(ПланыСчетов.Хозрасчетный.СкладскойУчет);
МассивСчетов.Добавить(ПланыСчетов.Хозрасчетный.Касса);
Запрос.УстановитьПараметр("МассивСчетов", МассивСчетов);
// В запросе: ГДЕ Ссылка В (&МассивСчетов)
Однако стоит помнить: если массив содержит тысячи элементов, производительность запроса может снизиться. В таких случаях лучше использовать временные таблицы.
Часто под задачей "выбрать диапазон" бухгалтер подразумевает: "возьмите этот счет и все его субсчета". В этом случае использование МЕЖДУ будет избыточным и сложным. Правильнее применить оператор В ИЕРАРХИИ.
Рассмотрим пример:
Запрос.Текст =
"ВЫБРАТЬ
| Хозрасчетный.Ссылка
|ИЗ
| ПланСчетов.Хозрасчетный КАК Хозрасчетный
|ГДЕ
| Хозрасчетный.Ссылка В ИЕРАРХИИ (&ОсновнойСчет)";
Этот метод автоматически включит в выборку сам счет и все вложенные уровни субсчетов, независимо от их кодов и порядка.
Если ваша задача — получить итоги (остатки или обороты) по диапазону счетов, крайне важно накладывать фильтр не в секции ГДЕ, а в параметрах виртуальной таблицы. Это критически важно для производительности системы.
Проанализируем ситуацию: когда мы накладываем условие в ГДЕ, система сначала выбирает все итоги из базы, а потом "отсеивает" лишние. Если мы передаем условие в параметры виртуальной таблицы, 1С запрашивает у СУБД уже отфильтрованные данные.
Пример для виртуальной таблицы Остатки:
Условие = "Счет В (&МассивСчетов)"; // Или через Порядок
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстатки.Счет,
| ХозрасчетныйОстатки.СуммаОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(&Период, , &УсловиеСчета, ) КАК ХозрасчетныйОстатки";
Запрос.УстановитьПараметр("УсловиеСчета", СписокСчетов);
Для достижения максимальной эффективности при работе с большими планами счетов или сложными выборками, придерживайтесь следующих правил:
Ссылка и Порядок всегда индексированы. Старайтесь строить условия именно по ним.ВНУТРЕННЕЕ СОЕДИНЕНИЕ с основной таблицей.ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ИмяСчета), это избавляет от лишних параметров в коде.Таким образом, мы выяснили, что наиболее правильным способом выбора диапазона "от и до" является использование реквизита Порядок, а для выбора групп счетов — оператор В ИЕРАРХИИ или передача подготовленного массива ссылок в параметры запроса.