При разработке отчетов или кастомных алгоритмов в современных конфигурациях на базе платформы 1С:Предприятие 8.3 (таких как ERP 2.5, Управление торговлей 11 или Комплексная автоматизация) программисты часто сталкиваются с неожиданным поведением запросов при попытке фильтрации по типу. Типичная ситуация: вы пытаетесь отобрать данные из регистра накопления РасчетыСПоставщиками, используя привычную конструкцию ССЫЛКА или ТИПЗНАЧЕНИЯ(), но система выдает ошибку «Несовместимые типы» или просто не возвращает результат. Разберем детально, почему это происходит и как правильно строить такие запросы.
Рассмотрим стандартную ситуацию. Программист пишет запрос к остаткам регистра накопления, пытаясь получить данные только по конкретному документу, например, ЗаказПоставщику:
ВЫБРАТЬ
РасчетыСПоставщикамиОстатки.ОбъектРасчетов КАК ОбъектРасчетов,
РасчетыСПоставщикамиОстатки.СуммаОстаток КАК СуммаОстаток
ИЗ
РегистрНакопления.РасчетыСПоставщиками.Остатки КАК РасчетыСПоставщикамиОстатки
ГДЕ
ТИПЗНАЧЕНИЯ(РасчетыСПоставщикамиОстатки.ОбъектРасчетов) = ТИП(Документ.ЗаказПоставщику)
На первый взгляд запрос корректен. Однако в современных редакциях типовых решений поле ОбъектРасчетов претерпело значительные архитектурные изменения. Выясним причину ошибки: раньше это поле действительно имело составной тип (Composite Type), включающий в себя ссылки на различные документы (заказы, накладные, договоры). В новых версиях разработчики фирмы «1С» перешли к использованию специального справочника-разделителя — Справочник.ОбъектыРасчетов.
Важный нюанс: Теперь в регистре хранится ссылка не на сам документ, а на элемент этого справочника. Попытка сравнить ссылку на справочник с типом документа в конструкции ТИП(Документ.ЗаказПоставщику) закономерно приводит к ошибке «Несовместимые типы», так как справочник никогда не может стать документом.
Проанализируем структуру справочника ОбъектыРасчетов. В нем обычно присутствует реквизит (например, с именем Объект), который и хранит реальную ссылку на документ или договор. Чтобы наше условие заработало, нам нужно «пробросить» обращение через этот реквизит. Посмотрим на правильный пример кода:
ВЫБРАТЬ
РасчетыСПоставщикамиОстатки.ОбъектРасчетов КАК ОбъектРасчетов,
РасчетыСПоставщикамиОстатки.СуммаОстаток КАК СуммаОстаток
ИЗ
РегистрНакопления.РасчетыСПоставщиками.Остатки КАК РасчетыСПоставщикамиОстатки
ГДЕ
РасчетыСПоставщикамиОстатки.ОбъектРасчетов.Объект ССЫЛКА Документ.ЗаказПоставщику
В данном случае мы используем оператор ССЫЛКА. Это наиболее оптимальный способ проверки типа в языке запросов 1С. Рассмотрим подробнее, почему стоит отдавать предпочтение именно ему.
При работе с высоконагруженными системами (ERP, КА) крайне важно учитывать производительность. Проанализируем, как эти две конструкции транслируются на уровень SQL:
_TYPE в таблицах SQL). Это очень быстрая операция, которая не требует дополнительных соединений таблиц.ГДЕ она может приводить к менее оптимальному плану выполнения запроса, особенно если в левой части выражения стоит реквизит составного типа.Совет: Всегда используйте Поле ССЫЛКА Тип вместо ТИПЗНАЧЕНИЯ(Поле) = ТИП(Тип), если вам нужно просто проверить принадлежность значения к конкретному объекту метаданных.
Если вам нужно не только отфильтровать данные по типу, но и получить доступ к специфическим полям документа (например, дате заказа или складу), рекомендуется использовать функцию ВЫРАЗИТЬ. Это позволяет системе «понять», с какой конкретно таблицей нужно соединиться.
Рассмотрим пример:
ВЫБРАТЬ
ВЫРАЗИТЬ(РасчетыСПоставщикамиОстатки.ОбъектРасчетов.Объект КАК Документ.ЗаказПоставщику).Дата КАК ДатаЗаказа,
РасчетыСПоставщикамиОстатки.СуммаОстаток КАК СуммаОстаток
ИЗ
РегистрНакопления.РасчетыСПоставщиками.Остатки КАК РасчетыСПоставщикамиОстатки
ГДЕ
РасчетыСПоставщикамиОстатки.ОбъектРасчетов.Объект ССЫЛКА Документ.ЗаказПоставщику
Важно помнить, что функция ВЫРАЗИТЬ вернет NULL, если тип значения не совпадает с указанным. Поэтому проверка на ССЫЛКА в условии ГДЕ остается обязательной для корректной фильтрации строк.
Часто в запросах мы видим использование Определяемых типов (Defined Types). Выясним причину, по которой конструкция ТИП(ОпределяемыйТип.ИмяТипа) не поддерживается в запросах. Определяемый тип — это объект метаданных, который на этапе компиляции разворачивается в список конкретных типов. SQL-сервер ничего не знает об «Определяемом типе», он работает с конкретными таблицами и идентификаторами типов. Поэтому в запросах мы всегда должны указывать конечный объект: Документ.Имя или Справочник.Имя.
В типовых конфигурациях для ускорения работы с регистром РасчетыСПоставщиками разработчики часто добавляют в справочник ОбъектыРасчетов вспомогательный реквизит, например, ТипОбъекта (перечисление). Если ваша задача — отобрать все заказы, а не только ЗаказПоставщику (включая, например, заказы переработчикам), проверьте наличие такого реквизита. Фильтрация по перечислению будет работать быстрее, чем проверка типа через точку от справочника.
Проанализировав ситуацию, можно составить краткий чек-лист для работы с типами в запросах:
ОбъектРасчетов — это почти всегда ссылка на одноименный справочник.Поле.Реквизит ССЫЛКА Тип.ТИПЗНАЧЕНИЯ(ПустаяСсылкаДокумента) вернет тот же тип, что и заполненная ссылка. Если вам нужны только заполненные объекты, добавьте проверку НЕ Поле ЕСТЬ NULL или сравнение с ЗНАЧЕНИЕ(...ПустаяСсылка).Следуя этим правилам, вы сможете избежать ошибок несовместимости типов и писать производительный код для работы с учетными механизмами платформы 1С:Предприятие 8.3.