К статье
Практический материал

Разработка и Конфигурация · 12 мин

Запрос 1С: отбор по ссылке в условии ГДЕ

Как в запросе 1С отобрать данные по ссылке: ГДЕ Ссылка = &Параметр, сравнение ссылок, ССЫЛКА в условии, работа с NULL и типичные ошибки с примерами кода.

Отбор по ссылке — одна из самых частых операций в запросах 1С: нужно получить накладные конкретного контрагента, движения по выбранному документу или остатки по номенклатуре. Конструкция выглядит просто — ГДЕ Таблица.Ссылка = &Параметр, но на практике именно здесь разработчики чаще всего получают пустые выборки, ошибки сравнения типов или неожиданно медленные запросы.

Причина почти всегда одна из трёх: параметр содержит не тот тип данных (например, строку вместо ссылки), сравнивается не то поле (реквизит вместо ссылки), или в запрос попадает NULL. Ниже разобраны рабочие конструкции, проверки результата и типовые ошибки с примерами кода.

Как устроена ссылка в запросе 1С

Ссылка — это поле Ссылка, которое есть у каждой таблицы ссылочного типа: справочников, документов, планов счетов, планов видов характеристик и других. Физически это уникальный идентификатор объекта в базе. В запросе ссылку можно сравнивать на равенство, использовать в соединениях и проверять оператором ССЫЛКА.

Важно понимать разницу: поле Ссылка — это сам объект-указатель, а реквизиты объекта (код, наименование, дата) доступны через точку от него. Поэтому ГДЕ Номенклатура.Ссылка = &Номенклатура и ГДЕ Номенклатура.Наименование = &Название — принципиально разные условия: первое сравнивает идентификаторы, второе — строки.

Поле Ссылка в тексте запроса обычно можно опустить: условие ГДЕ Товары.Номенклатура = &Номенклатура корректно, если реквизит Номенклатура имеет ссылочный тип. Явное обращение к .Ссылка требуется в основном тогда, когда нужно получить саму ссылку в результате запроса из составного реквизита или при работе с табличными частями документа.

Базовый отбор: ГДЕ Ссылка = &Параметр

Классический сценарий — получить конкретный документ или элемент справочника по известной ссылке. Параметр передаётся методом УстановитьПараметр объекта запроса.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Номер,

| РеализацияТоваровУслуг.Дата,

| РеализацияТоваровУслуг.Контрагент

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

Результат = Запрос.Выполнить();

Обратите внимание: в параметр передаётся значение типа ДокументСсылка.РеализацияТоваровУслуг, а не строка с номером и не представление объекта. Если передать строку, запрос не выдаст ошибку сравнения, но вернёт пустой результат — ссылка и строка никогда не равны.

Для отбора по нескольким ссылкам используется оператор В с массивом или списком значений:

"ГДЕ РеализацияТоваровУслуг.Ссылка В (&СписокСсылок)"

Запрос.УстановитьПараметр("СписокСсылок", МассивДокументов);

bsl
Запрос.Текст = "ВЫБРАТЬ Т.Ссылка ИЗ Справочник.Номенклатура КАК Т ГДЕ Т.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", НоменклатураСсылка);

Отбор по ссылке в реквизите и соединениях

Чаще всего ссылка сравнивается не в поле Ссылка самой таблицы, а в реквизите другого объекта. Например, нужно найти все документы по контрагенту или все строки табличной части по номенклатуре:

"ВЫБРАТЬ

| Реализация.Ссылка КАК Документ,

| Реализация.Дата

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Контрагент = &Контрагент

| И Реализация.Проведен"

В соединениях ссылка — основной ключ связи. Типичный пример: соединить документ с его табличной частью или регистр сведений со справочником:

"ВЫБРАТЬ

| Товары.Номенклатура,

| Товары.Количество

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка = &Документ"

Здесь Товары.Ссылка — это ссылка на документ-владелец табличной части. Это стандартный и самый быстрый способ получить строки конкретного документа: платформа использует индекс по ссылке.

Проверка типа: оператор ССЫЛКА в условии ГДЕ

Когда реквизит имеет составной тип (например, «Документ.РеализацияТоваровУслуг ИЛИ Документ.ПоступлениеТоваровУслуг»), часто нужно отобрать только один вид документов. Для этого служит оператор ССЫЛКА:

"ВЫБРАТЬ

| Взаиморасчеты.Регистратор

|ИЗ

| РегистрНакопления.ВзаиморасчетыСКонтрагентами КАК Взаиморасчеты

|ГДЕ

| Взаиморасчеты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг"

Этот приём полезен и в обратную сторону — когда нужно исключить определённый тип: ГДЕ НЕ Регистратор ССЫЛКА Документ.КорректировкаВзаиморасчетов. Без такой проверки в выборку попадут все виды документов-регистраторов, и последующее обращение к специфичному реквизиту даст NULL для чужих типов.

Для проверки, что ссылка не пустая, используется сравнение со значением ЗНАЧЕНИЕ(...):

"ГДЕ Номенклатура.Родитель <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)"

Альтернатива — функция ЕПУСТАЯССЫЛКА(Поле), но сравнение со ЗНАЧЕНИЕ(...) читается однозначнее и работает в обе стороны (проверка на пустую и на непустую ссылку).

Способы проверить ссылку

ССЫЛКА Документ.Вид

Проверяет тип значения в составном поле. Подходит для регистраторов, владельцев и любых составных реквизитов.

= ЗНАЧЕНИЕ(...ПустаяСсылка)

Проверяет, что ссылка пустая или заполненная. Работает только с конкретным типом, указанным в ЗНАЧЕНИЕ.

Поле ЕСТЬ NULL

Проверяет отсутствие значения после левого соединения. Не заменяет проверку на пустую ссылку — это разные состояния.

NULL, пустые ссылки и отбор по иерархии

Три состояния, которые разработчики регулярно путают: NULL, пустая ссылка и отсутствие строки. NULL появляется в результате левого соединения, когда пары не нашлось. Пустая ссылка — реальное значение в базе (поле заполнено «пустым» объектом). Отсутствие строки означает, что запись вообще не попала в выборку.

Правила простые: после левого соединения проверяйте ЕСТЬ NULL; для полей основной таблицы проверяйте пустую ссылку через ЗНАЧЕНИЕ(...). Сравнение NULL = ПустаяСсылка не даст истины никогда.

Отдельный частый сценарий — отбор по группе справочника с учётом иерархии. Здесь ссылка сравнивается через оператор В ИЕРАРХИИ:

"ВЫБРАТЬ

| Номенклатура.Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)"

Такой запрос вернёт все элементы группы и всех её подгрупп любой вложенности. Для неиерархических объектов (документы, регистры) оператор неприменим — попытка использовать его вызовет ошибку запроса.

Типичные ошибки при отборе по ссылке

Первая и самая массовая ошибка — передача в параметр строки или уникального идентификатора вместо ссылки. Значение ДокументСсылка.УникальныйИдентификатор() — это не ссылка, и сравнение с полем Ссылка не сработает. Если у вас есть только УИД (например, из внешней системы), ссылку нужно получить методом ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаУИД)) менеджера соответствующего объекта.

Вторая ошибка — обращение через точку к реквизиту составного поля без сужения типа. Выражение Регистратор.Номер для составного регистратора заставляет платформу соединяться со всеми таблицами документов-регистраторов, что резко замедляет запрос. Правильный приём — функция ВЫРАЗИТЬ(Регистратор КАК Документ.РеализацияТоваровУслуг).Номер совместно с условием ССЫЛКА.

Третья группа проблем — отбор по ссылке во временной таблице без индексации. Если вы помещаете ссылки во временную таблицу и потом соединяете её с большим регистром, добавьте ИНДЕКСИРОВАТЬ ПО Ссылка в запрос создания временной таблицы. На малых объёмах разницы не будет, на крупных регистрах — кратное ускорение.

Типичные ошибки
01
Передача строки или УИД вместо ссылки — запрос возвращает пустой результат без ошибки, и причину трудно найти.
02
Сравнение NULL с пустой ссылкой — условие никогда не выполняется, записи «теряются» после левого соединения.
03
Обращение к реквизиту составной ссылки через точку без ВЫРАЗИТЬ — запрос соединяется со всеми таблицами типов и работает медленно.
04
Отбор В ИЕРАРХИИ по неиерархическому объекту — ошибка выполнения запроса.
05
Отсутствие ИНДЕКСИРОВАТЬ ПО во временной таблице со ссылками — соединение с регистром выполняется полным перебором.

Проверка результата и отладка

Быстрый способ убедиться, что отбор по ссылке работает, — выполнить запрос в консоли запросов (внешняя обработка или встроенная консоль в режиме толстого клиента) и подставить реальную ссылку. Если выборка пустая, проверяйте по шагам: тип параметра, заполненность параметра, наличие записей в таблице вообще.

Полезный диагностический приём — временно убрать условие ГДЕ и вывести первые 10 строк таблицы, взяв поле ссылки в результат. Сравните визуально: совпадает ли тип значения в выборке с типом параметра. Если в выборке «Документ.РеализацияТоваровУслуг», а в параметре «Документ.РеализацияТоваров» (другая конфигурация или другое имя документа), проблема найдена.

В коде проверить параметр можно до выполнения запроса:

Если НЕ ЗначениеЗаполнено(ДокументСсылка) Тогда

ВызватьИсключение "Не передана ссылка для отбора";

КонецЕсли;

Такая проверка отсекает ситуацию, когда запрос честно отработал, но параметр был пуст, и вместо данных программа молча получила пустую выборку.

Контрольные точки

Как проверить результат

Тип параметра в отладчике
Норма

ДокументСсылка.<вид> или СправочникСсылка.<вид>

Тревожный признак

Строка, УникальныйИдентификатор, Неопределено

Результат запроса
Норма

Выборка содержит ожидаемые строки, поля ссылок заполнены

Тревожный признак

Пустая выборка при заведомо существующих данных

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

Проверка ЕСТЬ NULL отрабатывает, NULL обработан через ЕСТЬNULL

Тревожный признак

NULL попадает в сравнения и вычисления без обработки

Время выполнения на большой таблице
Норма

Запрос выполняется быстро, используется индекс по ссылке

Тревожный признак

Заметная задержка при обращении к реквизитам составной ссылки через точку

FAQ: частые вопросы об отборе по ссылке

Можно ли сравнить ссылку со строкой её представления?

Нет. Ссылка и строка — разные типы, сравнение всегда даст ложь, а запрос вернёт пустой результат. Если известно только наименование, отбирайте по реквизиту Наименование, но помните, что наименования могут совпадать у разных элементов.

Как найти объект по уникальному идентификатору в запросе?

Напрямую в запросе — никак, УИД не является полем таблицы. Сначала в коде получите ссылку: Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаУИД)), затем передайте её в параметр запроса.

Чем отличается ГДЕ Ссылка = &Параметр от ГДЕ Ссылка В (&Параметр)?

Равенство работает с одним значением, оператор В — с массивом или списком значений. Если в параметр с оператором В передать одиночную ссылку, а не коллекцию, запрос выдаст ошибку.

Почему условие по ссылке регистратора работает медленно?

Само сравнение ссылок быстрое. Медленным запрос становится, если вы через точку обращаетесь к реквизитам составного регистратора. Используйте ВЫРАЗИТЬ с явным типом и условие ССЫЛКА — тогда платформа соединится только с нужной таблицей.

Как отобрать записи, где ссылочное поле не заполнено?

Сравните поле со значением пустой ссылки конкретного типа: ГДЕ Поле = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Проверка ЕСТЬ NULL здесь не подойдёт — она предназначена для результатов соединений.

Работает ли отбор В ИЕРАРХИИ для документов?

Нет. Оператор В ИЕРАРХИИ применим только к иерархическим справочникам и планам видов характеристик. Для документов аналогичной вложенности нет, и попытка использовать оператор приведёт к ошибке запроса.

Итог

Что важно запомнить

Отбор по ссылке — это ГДЕ Поле = &Параметр с параметром ссылочного типа. Для составных полей используйте ССЫЛКА и ВЫРАЗИТЬ, для иерархии — В ИЕРАРХИИ, для пустых значений — ЗНАЧЕНИЕ(...ПустаяСсылка), а NULL после соединений обрабатывайте отдельно. Пустая выборка почти всегда означает неверный тип или незаполненный параметр.