Ссылка в запросе 1С: оператор ССЫЛКА и поля через точку

Дата: 21.09.2026 08:38:56
Запросы
Язык запросов
Ссылка
Составной тип
ВЫРАЗИТЬ
Оптимизация запросов
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Любые

Ссылка в запросе 1С встречается в трёх ролях: как поле Ссылка, по которому отбирают конкретный документ или элемент справочника; как операнд оператора ССЫЛКА, который проверяет тип значения в поле составного типа; и как отправная точка для получения реквизитов «через точку». С первым всё просто, а на втором и третьем ошибаются чаще всего: запрос по регистру с Регистратор.Номер выглядит безобидно, а в SQL превращается в длинную цепочку соединений. Ниже — синтаксис для платформы 8.3, готовый пример для регистра накопления и разбор того, во что обходится разыменование. Проверка на пустую ссылку и её отличие от NULL разобраны отдельно, в статье «Пустая ссылка в запросе».

Поле «Ссылка» и отбор по ссылке на документ

У каждой таблицы ссылочного объекта (справочника, документа, плана видов характеристик, плана счетов) есть стандартный реквизит Ссылка. Это уникальный ключ записи, и по нему в таблице всегда есть индекс, поэтому отбор по ссылке — самый быстрый способ найти одну запись. Ссылку на документ в запрос передают параметром:

&НаСервереБезКонтекста
Функция ДанныеРеализации(Знач Ссылка)

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

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

	Возврат Результат;

КонецФункции

Функция — для модуля формы: объекта Запрос на клиенте нет, а данные формы не нужны, отсюда &НаСервереБезКонтекста. Чтобы отобрать несколько документов, условие меняют на Реализация.Ссылка В (&Ссылки) и передают в параметр массив ссылок. У табличной части тоже есть поле Ссылка: в таблице Документ.РеализацияТоваровУслуг.Товары это ссылка на документ-владелец, так что Товары.Ссылка.Дата вернёт дату из шапки. Основы синтаксиса — в статье о языке запросов, выборка документов за период — в материале про запрос к документам.

В конфигурациях на БСП то же делают функции серверного модуля ОбщегоНазначения: ЗначениеРеквизитаОбъекта(Ссылка, "Контрагент") и ЗначенияРеквизитовОбъекта(Ссылка, "Номер, Дата, Контрагент"), вторая возвращает структуру. Они есть в БСП 2.x и 3.x, но необязательные параметры в редакциях отличаются — сверяйтесь с описанием в своей конфигурации.

Оператор ССЫЛКА: проверка типа ссылки в запросе 1С

Оператор ССЫЛКА отвечает на вопрос «ссылка какого вида лежит в этом поле». Синтаксис: <Выражение> ССЫЛКА <ИмяТаблицы>. Имя таблицы пишется так же, как в секции ИЗ, в единственном числе и без кавычек: Документ.РеализацияТоваровУслуг, Справочник.Контрагенты. Результат логический, поэтому оператор ставят в ГДЕ и в ветки ВЫБОР КОГДА.

Нужен он там, где у поля составной тип:

ПолеГде встречаетсяЧто в нём лежит
Регистраторрегистры накопления, бухгалтерии, расчёта; регистры сведений, подчинённые регистраторуссылка на любой документ, который делает движения по регистру
СубконтоДт1, СубконтоКт1 и следующие (в регистре без корреспонденции — Субконто1 и следующие)таблица движений регистра бухгалтериизначение любого типа, разрешённого для вида субконто: чаще ссылка на справочник, документ или перечисление, реже примитивное значение
Ссылка журнала документовжурналы документовссылка на один из документов, входящих в журнал
Реквизиты вроде «Основание», «Объект», «Владелец»справочники и документы с реквизитом составного типанабор типов, который задал разработчик

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

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

Отрицание записывается через НЕ: НЕ Продажи.Регистратор ССЫЛКА Документ.КорректировкаРеализации. Несколько видов перечисляют через ИЛИ, и если рядом есть условия через И, группу ИЛИ обязательно берут в скобки.

Три свойства оператора, которые стоит держать в голове:

  • Он дешёвый. В составном поле вид объекта хранится в отдельной колонке, и ССЫЛКА сравнивает только её — без соединения с таблицей документа.
  • Он проверяет только тип. Пустая ссылка на реализацию условию ССЫЛКА Документ.РеализацияТоваровУслуг удовлетворяет. Заполненность проверяется отдельно — сравнением с пустой ссылкой.
  • С NULL и Неопределено условие не выполняется. Строка с NULL в поле из левого соединения не пройдёт ГДЕ, а в ВЫБОР уйдёт в ветку ИНАЧЕ.

Тот же результат даёт сравнение типов: ТИПЗНАЧЕНИЯ(Продажи.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг). Запись длиннее, зато тип можно вынести в параметр: условие ТИПЗНАЧЕНИЯ(Продажи.Регистратор) В (&ТипыДокументов) с массивом значений вида Тип("ДокументСсылка.РеализацияТоваровУслуг") удобно, когда список видов собирается в коде по настройкам.

Поля через точку и цена разыменования

Запись Реализация.Контрагент.ИНН — сокращение. СУБД не умеет переходить по ссылкам, поэтому при трансляции запроса платформа добавляет неявное левое соединение: таблицу документов соединяет с таблицей контрагентов по ссылке и берёт ИНН оттуда. Каждая точка после ссылочного поля — ещё одно соединение: Реализация.Контрагент.ГоловнойКонтрагент.ИНН даст два. Для поля одного типа это приемлемо: соединение идёт по индексу и стоит как такое же, написанное вручную.

С составным типом картина другая. Платформа заранее не знает, документ какого вида лежит в Регистратор, и соединяет таблицу регистра со всеми таблицами, ссылки на которые могут быть в этом поле. Если регистраторов у регистра двадцать, соединений будет двадцать — и это ради одного Продажи.Регистратор.Дата. У реквизитов с типом «любая ссылка» или «любой документ» счёт идёт на все таблицы такого вида в конфигурации. Если в базе настроено ограничение доступа на уровне записей, к присоединённым таблицам могут добавиться ещё и условия ограничений. Оптимизатору СУБД с таким текстом тяжело, и запрос, мгновенный на тестовой базе, на рабочей может идти минутами. Об этом отдельно предупреждает стандарт 1С «Разыменование ссылочных полей составного типа в языке запросов».

Лечится это функцией ВЫРАЗИТЬ. Было:

ВЫБРАТЬ
	Продажи.Регистратор.Контрагент КАК Контрагент,
	Продажи.Сумма КАК Сумма
ИЗ
	РегистрНакопления.Продажи КАК Продажи

Стало:

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

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

Практические правила:

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

Если ссылка пустая, поле через точку от неё вернёт NULL: пары в присоединённой таблице нет. То же будет с полем составного типа, если нужного реквизита у документа этого вида нет.

Полный пример: продажи в разрезе документов-регистраторов

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

// Серверный общий модуль или модуль объекта отчета/обработки.
// Имена объектов метаданных условные: замените их на имена из своей конфигурации.

// Возвращает продажи за период в разрезе документов-регистраторов
// с номером, датой и контрагентом документа. Учитываются реализации
// и возвраты от клиентов, движения остальных документов отбрасываются.
//
// Параметры:
//  ДатаНачала    - Дата - начало периода.
//  ДатаОкончания - Дата - конец периода.
//
// Возвращаемое значение:
//  ТаблицаЗначений - колонки Регистратор, ВидДокумента, Номер, Дата,
//                    Контрагент, Количество, Сумма.
//
Функция ПродажиПоДокументам(Знач ДатаНачала, Знач ДатаОкончания) Экспорт

	Запрос = Новый Запрос;
	Запрос.Текст =
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	Продажи.Регистратор КАК Регистратор,
	|	СУММА(Продажи.Количество) КАК Количество,
	|	СУММА(Продажи.Сумма) КАК Сумма
	|ПОМЕСТИТЬ ВТ_Регистраторы
	|ИЗ
	|	РегистрНакопления.Продажи КАК Продажи
	|ГДЕ
	|	Продажи.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
	|	И (Продажи.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
	|			ИЛИ Продажи.Регистратор ССЫЛКА Документ.ВозвратТоваровОтКлиента)
	|
	|СГРУППИРОВАТЬ ПО
	|	Продажи.Регистратор
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	Регистраторы.Регистратор КАК Регистратор,
	|	ВЫБОР
	|		КОГДА Регистраторы.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
	|			ТОГДА ""Реализация""
	|		ИНАЧЕ ""Возврат""
	|	КОНЕЦ КАК ВидДокумента,
	|	ЕСТЬNULL(Реализация.Номер, Возврат.Номер) КАК Номер,
	|	ЕСТЬNULL(Реализация.Дата, Возврат.Дата) КАК Дата,
	|	ЕСТЬNULL(Реализация.Контрагент, Возврат.Контрагент) КАК Контрагент,
	|	Регистраторы.Количество КАК Количество,
	|	Регистраторы.Сумма КАК Сумма
	|ИЗ
	|	ВТ_Регистраторы КАК Регистраторы
	|		ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
	|		ПО Регистраторы.Регистратор = Реализация.Ссылка
	|		ЛЕВОЕ СОЕДИНЕНИЕ Документ.ВозвратТоваровОтКлиента КАК Возврат
	|		ПО Регистраторы.Регистратор = Возврат.Ссылка
	|
	|УПОРЯДОЧИТЬ ПО
	|	Дата";

	Запрос.УстановитьПараметр("ДатаНачала", НачалоДня(ДатаНачала));
	Запрос.УстановитьПараметр("ДатаОкончания", КонецДня(ДатаОкончания));

	Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

Разбор ключевых строк

  • ССЫЛКА в ГДЕ первого запроса. Отсекает движения остальных документов без соединения с их таблицами: сравнивается только вид ссылки.
  • РАЗРЕШЕННЫЕ в обоих запросах. Если в базе включено ограничение доступа на уровне записей, недоступные пользователю движения и документы не попадут в отчёт. Без РАЗРЕШЕННЫЕ запрос завершился бы ошибкой «Недостаточно прав».
  • СГРУППИРОВАТЬ ПО Регистратор до соединений. Строки движений одного документа сворачиваются в одну. Дальше соединения выполняются по числу документов, а не по числу строк регистра.
  • Два ЛЕВОЕ СОЕДИНЕНИЕ по полю Ссылка. Вместо Регистратор.Номер, который соединил бы регистр со всеми таблицами регистраторов, — ровно две таблицы. Для реализации пара найдётся только в первой, поля второй будут NULL, поэтому ЕСТЬNULL берёт значение из той таблицы, где пара нашлась. ССЫЛКА в условии соединения не нужна: равенство ссылок уже включает совпадение типа.
  • ВЫБОР с ССЫЛКА. Вид документа для отчёта. Ветка ИНАЧЕ безопасна: первый запрос оставил только два вида.
  • НачалоДня и КонецДня. Если дату окончания передали без времени, без КонецДня движения последнего дня выпали бы из выборки.

Вариант с ВЫРАЗИТЬ тоже сработал бы, но три поля на два вида документов — это шесть выражений внутри ВЫБОР, читать такое тяжелее.

Типичные ошибки

  • Множественное число или кавычки справа от ССЫЛКА. Регистратор ССЫЛКА Документы.РеализацияТоваровУслуг или ССЫЛКА "Документ.РеализацияТоваровУслуг" — запрос не выполнится. Платформа сообщит об ошибке в тексте запроса и укажет строку и позицию в фигурных скобках, например {(9, 33)}. Справа всегда имя таблицы, как в секции ИЗ.
  • Опечатка в поле через точку. Реализация.Контрагент.ИН вместо ИНН даст ошибку «Поле не найдено» с именем поля. Всплывёт она только при выполнении; заранее её покажет конструктор запроса.
  • Точка от Регистратора в большом регистре. Ошибки нет, но запрос медленный. Замените на ВЫРАЗИТЬ или явное соединение.
  • ВЫРАЗИТЬ без отбора по ССЫЛКА. Для строк других видов реквизиты придут как NULL, и в отчёте появятся строки с пустым контрагентом.
  • Разыменование в цикле по выборке. Выборка.Контрагент.ИНН в коде — это чтение из базы на каждой строке с новым контрагентом, причём платформа считывает объект целиком, а не одно поле. Нужный реквизит получайте в самом запросе.
  • Точка от ссылки на клиенте. В процедуре с директивой &НаКлиенте обращение Объект.Контрагент.ИНН завершится ошибкой «Поле объекта не обнаружено (ИНН)»: на клиенте ссылка не даёт доступа к реквизитам объекта. Значение нужно получить на сервере.

Частые вопросы

Чем ССЫЛКА отличается от ТИПЗНАЧЕНИЯ()?

По результату — ничем: Поле ССЫЛКА Документ.X и ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.X) отбирают одни и те же строки. ССЫЛКА короче и читается проще. ТИПЗНАЧЕНИЯ нужен, когда тип приходит параметром или его надо вывести в результат запроса как отдельную колонку.

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

Функцией ТипЗнч(): ТипЗнч(Значение) = Тип("ДокументСсылка.РеализацияТоваровУслуг"). Чтобы проверить, что значение — ссылка на любой документ, используют описание типов от менеджера: Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)). Для справочников — аналогично через Справочники.ТипВсеСсылки().

Работают ли ССЫЛКА и ВЫРАЗИТЬ в СКД и динамическом списке?

Да: набор данных СКД и запрос динамического списка пишутся на том же языке запросов. В отчётах на СКД по регистрам ВЫРАЗИТЬ особенно полезен — поле через точку от регистратора замедляет каждое формирование.

Почему Регистратор.Дата не всегда совпадает с Период?

Период записывает код проведения. Обычно это дата документа, но код может записать и другую дату, например дату отгрузки из табличной части. Для отчётов по движениям правильнее брать Период: он уже есть в таблице регистра и не требует соединений.

Когда проще заказать

Если отчёт по регистру тормозит из-за разыменований или нужен новый отчёт на СКД с данными документов-регистраторов, задачу можно передать программисту. На 1c-only.ru можно заказать разработку отчётов и обработок 1С или разместить задачу: оценка бесплатная, ответ в течение рабочего дня. Если медленно работает не один отчёт, а вся база, посмотрите услугу «1С тормозит».

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.