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