Как правильно установить условие по типу данных в запросе 1С 8.2 и 8.3

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

При разработке отчетов и обработок в системе 1С:Предприятие программисты часто сталкиваются с ситуацией, когда одно поле (например, Артикул или Номенклатура) имеет составной тип данных. В такой ситуации стандартные условия могут работать некорректно или существенно замедлять систему. Разберем на практическом примере, как эффективно отсечь лишние типы данных и оптимизировать запрос.

Постановка задачи

Представим ситуацию: в регистре накопления хранятся остатки. Поле Артикул имеет составной тип, включающий справочники Артикулы и Услуги. Нам необходимо выбрать остатки только по тем записям, где в поле Артикул указана ссылка на справочник Артикулы, исключив услуги и прочие объекты. Рассмотрим, почему базовый подход через ТИПЗНАЧЕНИЯ может не сработать и какие альтернативы существуют.

Проблема использования ТИПЗНАЧЕНИЯ

Многие начинающие разработчики пытаются использовать конструкцию ГДЕ ТИПЗНАЧЕНИЯ(Поле) = ТИП(Справочник.ИмяСправочника). Хотя синтаксически это верно, на уровне SQL-запроса это заставляет сервер выполнять сравнение идентификаторов типов для каждой строки. Это не самый оптимальный путь, особенно для виртуальных таблиц. Более того, при определенных настройках прав доступа или наличии пустых значений такая проверка может пропускать данные, которые мы хотели отфильтровать.

Решение №1: Использование оператора ССЫЛКА

Наиболее правильным и быстрым способом проверки типа в языке запросов 1С является оператор ССЫЛКА. Проанализируем, как должен выглядеть запрос:


ВЫБРАТЬ
    СкладОстатки.Артикул КАК Артикул,
    СкладОстатки.КоличествоОстаток КАК Наличие
ИЗ
    РегистрНакопления.Склад41000Центральный.Остатки КАК СкладОстатки
ГДЕ
    СкладОстатки.Артикул ССЫЛКА Справочник.Артикулы

Важный нюанс: оператор ССЫЛКА возвращает Истина, если значение в поле относится к указанному типу. Если в поле хранится NULL или Неопределено, результат будет Ложь, что автоматически отсеивает пустые записи составного типа.

Решение №2: Фильтрация в параметрах виртуальной таблицы

Одной из самых частых ошибок является установка условия в секции ГДЕ при обращении к виртуальным таблицам (Остатки, Обороты). Разберем по шагам, почему это плохо: когда условие стоит в ГДЕ, система сначала рассчитывает итоги по всем записям регистра (включая услуги), и только потом отфильтровывает результат. Если записей миллионы, запрос будет "тормозить".

Правильнее передавать условие в параметры самой виртуальной таблицы. Посмотрим на пример:


ВЫБРАТЬ
    СкладОстатки.Артикул,
    СкладОстатки.КоличествоОстаток
ИЗ
    РегистрНакопления.Склад41000Центральный.Остатки(, Артикул ССЫЛКА Справочник.Артикулы) КАК СкладОстатки

В этом случае платформа 1С передаст фильтр на уровень СУБД, и расчет остатков будет производиться только по нужным нам артикулам. Это кардинально повышает производительность.

Решение №3: Обработка пустых ссылок

Иногда оператор ССЫЛКА пропускает "пустые ссылки" конкретного типа. То есть объект является артикулом, но сама ссылка пустая. Если нам нужно исключить и их, добавим дополнительное условие:


ГДЕ
    СкладОстатки.Артикул ССЫЛКА Справочник.Артикулы
    И СкладОстатки.Артикул <> ЗНАЧЕНИЕ(Справочник.Артикулы.ПустаяСсылка)

Оптимизация через оператор ВЫРАЗИТЬ

Когда мы работаем с составным типом и обращаемся к реквизитам через точку (например, Артикул.Стандарт), система 1С генерирует сложные соединения (LEFT JOIN) со всеми таблицами, входящими в составной тип. Чтобы этого избежать, используем оператор ВЫРАЗИТЬ.

Проанализируем ситуацию: если мы точно знаем, что в данной строке должен быть справочник Артикулы, мы "подсказываем" это системе. Рассмотрим исправленный фрагмент кода:


ВЫБРАТЬ
    СкладОстатки.Артикул,
    ВЫРАЗИТЬ(СкладОстатки.Артикул КАК Справочник.Артикулы).Стандарт КАК Стандарт,
    ВЫРАЗИТЬ(СкладОстатки.Артикул КАК Справочник.Артикулы).Обозначение КАК Обозначение
ИЗ
    РегистрНакопления.Склад41000Центральный.Остатки(, Артикул ССЫЛКА Справочник.Артикулы) КАК СкладОстатки

Такой подход гарантирует, что SQL-запрос обратится только к таблице справочника Артикулы, не пытаясь найти реквизит Стандарт в таблице Услуги.

Дополнительный метод: Фильтрация в цикле обхода (Post-processing)

Если по каким-то причинам изменить запрос невозможно (например, он формируется динамически в закрытом модуле), можно использовать проверку при обходе результата. Однако помните, что это наименее эффективный метод.


Пока Выборка.Следующий() Цикл
    // Проверяем, заполнено ли значение и является ли оно нужным типом
    Если Не ЗначениеЗаполнено(Выборка.Артикул) Тогда
        Продолжить;
    КонецЕсли;
    
    // Дополнительная проверка типа через встроенный язык
    Если ТипЗнч(Выборка.Артикул) <> Тип("СправочникСсылка.Артикулы") Тогда
        Продолжить;
    КонецЕсли;

    // Обработка данных...
КонецЦикла;

Использование временных таблиц для сложной фильтрации

Если типов в составе поля очень много, а фильтрация требуется сложная, воспользуемся методом временных таблиц. Разберем этот алгоритм:

  1. Создаем временную таблицу, в которую выбираем только нужные ссылки из справочника Артикулы (например, по определенной группе или свойству).
  2. Выполняем ВНУТРЕННЕЕ СОЕДИНЕНИЕ таблицы остатков с этой временной таблицей по полю Артикул.

Этот метод заставляет SQL-сервер использовать индексы для фильтрации, что является эталоном производительности в 1С.

Резюме и рекомендации

Подведем итоги нашего анализа. Чтобы эффективно работать с условиями в запросах 8.2/8.3, придерживайтесь следующих правил:

Соблюдение этих простых правил не только решит проблему с "лишними" данными в выборке, но и сделает вашу конфигурацию значительно быстрее и надежнее.

← На главную