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