В практике разработчика 1С часто возникает ситуация, когда в информационной базе создается множество документов с абсолютно одинаковой датой (с точностью до секунды). Это типично для пакетной обработки данных, загрузок из внешних систем или работы в высоконагруженных базах. В таких случаях стандартной сортировки по дате становится недостаточно. Мы начинаем задаваться вопросом: вернет ли функция МАКСИМУМ(Ссылка) в запросе действительно последний сформированный документ?
Разберем эту задачу подробно, проанализируем механизмы работы платформы и выясним, как СУБД обрабатывает ссылки на самом деле.
Для начала проанализируем, что представляет собой Ссылка (или GUID) с точки зрения базы данных. В 1С ссылка — это 128-битное число (UUID версии 1), которое хранится в SQL-таблицах в поле типа binary(16). Когда мы используем агрегатную функцию МАКСИМУМ к полю ссылки, платформа транслирует это в SQL-команду MAX().
Важно понимать следующие моменты:
Регистратор в регистрах, мы имеем дело с составным типом данных. В этом случае МАКСИМУМ сначала сравнивает идентификатор типа документа (внутренний номер метаданных), а уже затем — бинарные данные самой ссылки.Рассмотрим ситуацию, когда нам нужно получить последний приход по списку товаров, где документов в одной секунде может быть много. Просто применить МАКСИМУМ(Регистратор) в одном запросе с группировкой по номенклатуре может быть недостаточно, если в этой же секунде есть документы разных типов.
Разберем по шагам наиболее надежный метод с использованием временных таблиц:
Шаг 1. Получение максимальной даты (периода) для каждого объекта.
Сначала мы находим саму временную точку, в которой было совершено последнее движение.
ВЫБРАТЬ
Продажи.Номенклатура КАК Номенклатура,
МАКСИМУМ(Продажи.Период) КАК МаксПериод
ПОМЕСТИТЬ ВТ_МаксПериод
ИЗ
РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
;
Шаг 2. Получение максимальной ссылки внутри найденной секунды.
Теперь проанализируем ситуацию: в найденную секунду МаксПериод могло попасть несколько документов. Чтобы выбрать из них «самый последний», мы соединяем исходную таблицу с нашей временной таблицей и берем максимум по ссылке.
ВЫБРАТЬ
Продажи.Номенклатура КАК Номенклатура,
МАКСИМУМ(Продажи.Регистратор) КАК ПоследнийРегистратор
ИЗ
РегистрНакопления.Продажи КАК Продажи
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_МаксПериод КАК ВТ_МаксПериод
ПО Продажи.Номенклатура = ВТ_МаксПериод.Номенклатура
И Продажи.Период = ВТ_МаксПериод.МаксПериод
СГРУППИРОВАТЬ ПО
Продажи.Номенклатура
Такой двухэтапный подход гарантирует, что мы получим документ с максимальным бинарным значением ссылки внутри максимальной секунды. В 99% случаев это будет именно тот документ, который был введен последним.
Рассмотрим более простой вариант, если нам нужно получить только один, самый последний документ в целом (без группировки по списку товаров). В 1С объект МоментВремени — это комбинация Дата + Ссылка. Хотя мы не можем использовать МАКСИМУМ(МоментВремени) в языке запросов, мы можем использовать упорядочивание.
Посмотрим на пример:
ВЫБРАТЬ ПЕРВЫЕ 1
Док.Ссылка КАК ПоследнийДокумент
ИЗ
Документ.ПриходнаяНакладная КАК Док
УПОРЯДОЧИТЬ ПО
Док.МоментВремени УБЫВ
Этот способ является методологически самым верным, так как он напрямую использует механизм платформы для разрешения коллизий внутри одной секунды. При выполнении этого запроса СУБД фактически выполнит сортировку сначала по полю Дата, а затем по бинарному представлению GUID.
Проанализируем риски, которые могут привести к неожиданному результату. Несмотря на то, что обычно новые ссылки «больше» старых, существуют исключения:
УстановитьСсылкуНового(), разработчик может назначить документу абсолютно любой идентификатор, что нарушит естественный порядок.Регистратора (составной тип) решающую роль играет внутренний идентификатор метаданных. Если документ типа «А» имеет ID типа 10, а документ типа «Б» — ID 20, то при одинаковой дате МАКСИМУМ всегда выберет документ типа «Б», вне зависимости от времени его создания.Подведем итог нашему исследованию. Для того чтобы ваша система работала надежно, придерживайтесь следующих правил:
СрезПоследних) — платформа внутри них уже реализовала правильную логику работы с моментом времени.МАКСИМУМ(Период), затем МАКСИМУМ(Ссылка).МоментВремени везде, где это позволяет синтаксис (например, в параметрах виртуальных таблиц или при упорядочивании), так как это стандартный механизм платформы для обеспечения уникального порядка событий на временной оси.Таким образом, МАКСИМУМ(Ссылка) является рабочим инструментом в рамках одной секунды, но его использование требует понимания того, как устроены типы данных в 1С и как работает бинарное сравнение в СУБД.