Как в запросе 1С сравнить значение определяемого типа с конкретным типом документа

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При работе с типовыми конфигурациями (такими как УТ 11, ERP или КА) программисты часто сталкиваются с необходимостью фильтрации данных по конкретному типу документа в полях с составным или определяемым типом. Например, в регистре накопления РасчетыСКлиентамиПоСрокам измерение РасчетныйДокумент имеет определяемый тип, который включает в себя десятки различных документов. Рассмотрим подробнее, как правильно организовать проверку типа в запросе, разберем причины возможных ошибок и проанализируем логику работы виртуальных таблиц.

Понимание определяемого типа в запросе

Прежде всего, проанализируем, что представляет собой определяемый тип для механизма запросов. На уровне базы данных это обычный составной тип данных. В запросе вы работаете не с самим «определяемым типом» (который виден только в метаданных конфигуратора), а с конкретными типами ссылок, которые в него входят. Если документ ПоступлениеБезналичныхДенежныхСредств включен в состав определяемого типа, то вы можете использовать его для сравнения точно так же, как и любой другой ссылочный тип.

Способы сравнения типов в запросах

Рассмотрим основные способы проверки типа данных. В 1С существует два основных подхода, и важно понимать разницу между ними.

Способ 1. Использование оператора ССЫЛКА

Это наиболее предпочтительный и производительный способ. Он работает быстро, так как платформа на уровне SQL генерирует эффективную проверку по идентификатору типа. Разберем пример кода:


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

Способ 2. Использование функции ТИПЗНАЧЕНИЯ

Этот метод считается менее «изящным», но иногда встречается в старом коде. Синтаксис выглядит так:


ГДЕ
    ТИПЗНАЧЕНИЯ(Взаиморасчеты.РасчетныйДокумент) = ТИП(Документ.ПоступлениеБезналичныхДенежныхСредств)

Важно помнить: если при использовании ССЫЛКА или ТИПЗНАЧЕНИЯ вы получаете ошибку «Несовместимые типы», это однозначно сигнализирует о том, что тип Документ.ПоступлениеБезналичныхДенежныхСредств не входит в состав определяемого типа РасчетныйДокумент. В этом случае необходимо зайти в конфигуратор и проверить состав метаданных.

Различие между Регистратором и измерениями

Проанализируем распространенную ситуацию, когда запрос не выдает ошибок, но возвращает пустой результат. Часто это связано с путаницей между системным полем Регистратор и измерениями регистра.

  1. Поле Регистратор: Оно присутствует в таблице движений и в виртуальной таблице ОстаткиИОбороты (если указана соответствующая периодичность). В нем хранится ссылка на документ, который непосредственно создал запись в регистре.
  2. Измерение (например, РасчетныйДокумент): Это поле, которое заполняется при проведении документа программно. В него может быть записан совсем другой документ. Например, Регистратором может выступать «Поступление безналичных ДС», а Расчетным документом в этой же строке будет «Заказ клиента» или «Реализация товаров и услуг».

Если вы пытаетесь найти оплату, используя условие ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(...), убедитесь, что именно этот документ делает движения по данному регистру. Если документ является лишь «платежкой», он может вообще не делать движений по регистрам «по срокам», если в системе включена новая архитектура взаиморасчетов.

Особенности виртуальных таблиц и точка в запросе

Выясним причину, по которой использование конструкции Регистратор.Ссылка может замедлять запрос. При обращении через точку от поля составного типа платформа выполняет левое соединение (LEFT JOIN) со всеми таблицами, входящими в этот тип. Если в определяемом типе 50 документов, SQL-запрос превратится в громоздкую конструкцию. Для автоматического обнаружения подобных неэффективностей в текстах запросов можно использовать обработку для проверки запросов на лишние поля и разыменование полей составного типа.

Рассмотрим правила работы с точкой:

Для оптимизации рекомендуется использовать оператор ВЫРАЗИТЬ. Это позволяет жестко ограничить количество соединений только одной таблицей:


ВЫБРАТЬ
    ВЫРАЗИТЬ(Расчеты.Регистратор КАК Документ.ПоступлениеБезналичныхДенежныхСредств).Номер КАК НомерПлатежки
ИЗ
    РегистрНакопления.РасчетыСКлиентамиПоСрокам.ОстаткиИОбороты(,,, Регистратор,) КАК Расчеты
ГДЕ
    Расчеты.Регистратор ССЫЛКА Документ.ПоступлениеБезналичныхДенежныхСредств

Почему результат запроса может быть пустым

Если синтаксис верный, но данных нет, проанализируем следующие моменты:

  1. Периодичность виртуальной таблицы. В таблице ОстаткиИОбороты поле Регистратор будет заполнено только в том случае, если в параметрах таблицы указана периодичность Регистратор. При периодичности Авто, День или Период это поле будет содержать NULL, и условие по типу не сработает.
  2. Логика регистра. В УТ 11 регистр РасчетыСКлиентамиПоСрокам часто хранит в измерении РасчетныйДокумент объекты расчетов (заказы или накладные), а не документы оплаты. В таком случае поиск оплаты через это измерение по типу «Поступление безналичных ДС» всегда вернет пустое значение.
  3. Использование ТИПЗНАЧЕНИЯ для NULL. Если поле содержит NULL (например, при левом соединении), функция ТИПЗНАЧЕНИЯ(Поле) вернет NULL, что не равно значению ТИП(...).

Подводя итог, для корректного решения задачи используйте оператор ССЫЛКА, проверяйте состав определяемого типа в конфигураторе и всегда контролируйте настройки периодичности виртуальных таблиц при обращении к регистратору.

← На главную