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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При анализе сложных запросов в платформах 1С нередко можно встретить логические условия вида тбРегВзаимОстатки.РасчетныйДокумент <= тбРегВыпУсл.ДокументСобытия. На первый взгляд разработчику может показаться, что система автоматически сравнивает документы по их дате или моменту времени. Однако на практике результаты такого отбора оказываются непредсказуемыми. Разберем подробнее, как платформа 1С и СУБД обрабатывают сравнение ссылочных типов данных и как правильно решать подобные задачи.

Физика сравнения ссылок на уровне СУБД

В языке запросов 1С ссылки на документы или справочники не являются привычными датами или числами. Ссылка — это составной объект. При трансляции запроса к системе управления базами данных (Microsoft SQL Server, PostgreSQL и др.) платформа 1С преобразует сравнение ссылочных полей в побайтовое сравнение нескольких внутренних служебных колонок:

  1. _TYPE — байт, определяющий базовый тип данных (ссылка, число, строка, булево).
  2. _RTRef — 4-байтный внутренний идентификатор метаданных (конкретного вида документа или справочника).
  3. _RRRef — 16-байтный бинарный уникальный идентификатор записи (GUID / UUID).

Проанализируем ситуацию, когда сравниваются документы разных видов (например, Документ.ПриходныйКассовыйОрдер и Документ.РеализацияТоваровУслуг). В этом случае СУБД сравнивает значение поля _RTRef. Документ того вида, чей внутренний номер метаданных меньше, всегда будет считаться «меньше» другого документа, независимо от реальной даты их создания, номеров и физического порядка проведения.

Если же сравниваются документы одного вида, поле _RTRef совпадает, и СУБД переходит к побайтовому сравнению 16 байт поля _RRRef. Уникальные идентификаторы формируются платформой по определенным алгоритмам, но они не гарантируют строгого соответствия реальной хронологии. Если документы создавались последовательно в одном сеансе, их GUID могут располагаться по порядку. Однако при работе в параллельных сеансах или при загрузке данных порядок GUID становится псевдослучайным.

Ошибки при попытке заменить момент времени сравнением ссылок

Рассмотрим пример кода из реальной практики, где разработчик попытался связать таблицы по условию сравнения ссылок:


ВЫБРАТЬ РАЗРЕШЕННЫЕ
	тбРегВзаимОстатки.Организация,
	тбРегВзаимОстатки.Контрагент,
	тбРегВзаимОстатки.РасчетныйДокумент,
	тбРегВыпУсл.ДокументСобытия
ИЗ
	тбРегВзаимОстатки КАК тбРегВзаимОстатки
	ЛЕВОЕ СОЕДИНЕНИЕ тбРегВыпУсл КАК тбРегВыпУсл
		ПО тбРегВзаимОстатки.Организация = тбРегВыпУсл.Организация
		И тбРегВзаимОстатки.Контрагент = тбРегВыпУсл.Контрагент
		И (тбРегВзаимОстатки.РасчетныйДокумент <= тбРегВыпУсл.ДокументСобытия)

Использование операторов <, <=, >, >= для ссылочных типов с целью ограничить выборку по времени — это явная архитектурная ошибка. Результат выполнения такого запроса зависит только от внутренних идентификаторов СУБД, но никак не от реквизита Дата.

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

Выясним, как правильно решить задачу сопоставления документов по хронологии в языке запросов 1С.

Способ 1. Получение даты через оператор ВЫРАЗИТЬ

Если реквизит имеет составной ссылочный тип (например, РасчетныйДокумент), вызов поля Дата через точку напрямую невозможен или приводит к NULL. Чтобы обратиться к дате, необходимо явно привести ссылку к конкретному типу документа с помощью конструкции ВЫРАЗИТЬ:


ВЫБРАТЬ
	ВЫБОР
		КОГДА Таблица.РасчетныйДокумент ССЫЛКА Документ.ПоступлениеТоваровУслуг
			ТОГДА ВЫРАЗИТЬ(Таблица.РасчетныйДокумент КАК Документ.ПоступлениеТоваровУслуг).Дата
		КОГДА Таблица.РасчетныйДокумент ССЫЛКА Документ.ОтчетКомиссионера
			ТОГДА ВЫРАЗИТЬ(Таблица.РасчетныйДокумент КАК Документ.ОтчетКомиссионера).Дата
		ИНАЧЕ ДАТАВРЕМЯ(1, 1, 1)
	КОНЕЦ КАК ДатаРасчетногоДокумента
ИЗ
	РегистрНакопления.Взаиморасчеты КАК Таблица

Способ 2. Эмуляция момента времени в запросе (Дата + Ссылка)

Тип МоментВремени существует только во встроенном языке 1С и недоступен внутри запросов. Если требуется сравнить две точки на оси времени с точностью до позиции документа внутри секунды, используют составное условие по дате и ссылке:


ГДЕ
	(Документ1.Дата < Документ2.Дата)
	ИЛИ (Документ1.Дата = Документ2.Дата И Документ1.Ссылка <= Документ2.Ссылка)

В этом условии оператор <= для ссылок используется исключительно как «разрешитель ничьей» (tie-breaker), когда даты документов полностью совпадают с точностью до секунды. Это обеспечивает детерминированную и стабильную сортировку выборки.

Способ 3. Перенос логики на встроенный язык

Если алгоритм требует точной проверки объекта МоментВремени, разберем порядок действий на встроенном языке:

  1. Выбираем из базы необходимые документы и их даты с помощью запроса.
  2. В цикле обработки результата получаем объект момента времени методом Ссылка.ПолучитьМоментВремени().
  3. Сравниваем полученные объекты типа МоментВремени стандартными операторами языка 1С.

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

← На главную