Поле Регистратор в запросах к регистрам 1С
Содержание
Регистратор — это стандартное поле подчинённого регистра. Чтобы получить документ, который сделал запись в регистр, в запросе обращаются к полю Регистратор таблицы движений: ВЫБРАТЬ Регистратор ИЗ РегистрНакопления.ТоварыНаСкладах. Поле есть у регистров накопления, бухгалтерии и у регистров сведений, подчинённых регистратору.
Тип этого поля — составной (ДокументСсылка): в одном регистре движения делают разные документы, поэтому Регистратор может ссылаться на реализацию, поступление, корректировку и так далее. Из-за составного типа есть нюансы: реквизиты документа через точку тянут за собой неявные соединения, а в части виртуальных таблиц регистратора вообще нет. Разберём каждый случай с примерами запроса.
Где лежит поле Регистратор и как к нему обратиться
Регистратор появляется только у регистров, которые подчинены регистратору. Это:
- 📦 регистры накопления (
РегистрНакопления); - 📘 регистры бухгалтерии (
РегистрБухгалтерии); - 📑 регистры сведений с режимом записи «Подчинение регистратору».
У независимого регистра сведений регистратора нет — записи туда вносятся набором, без документа-владельца. Это первое, что стоит проверить, если поле Регистратор не находится в конструкторе запроса.
В основной (физической) таблице движений поле доступно всегда:
ВЫБРАТЬ
Движения.Регистратор КАК Регистратор,
Движения.Период,
Движения.Номенклатура,
Движения.Количество,
Движения.ВидДвижения
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Движения
ГДЕ
Движения.Активность
И Движения.Период МЕЖДУ &Начало И &Конец
Рядом с регистратором в таблице движений лежат служебные поля: Период — момент записи, НомерСтроки — номер строки движения внутри документа, Активность — признак, что запись участвует в итогах. Отбор ГДЕ Движения.Активность отсекает помеченные неактивными движения — их регистр не учитывает в остатках.
Если нужен не просто перечень документов, а фильтр по конкретному типу, используйте оператор ССЫЛКА: ГДЕ Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг. Так в выборку попадут только движения этого вида документа.
Движения упорядочивают по трём полям подряд — Период, Регистратор, НомерСтроки. Это даёт корректную хронологию: сначала по времени, затем по документу внутри одного момента, затем по строкам внутри документа.
УПОРЯДОЧИТЬ ПО
Движения.Период,
Движения.Регистратор,
Движения.НомерСтроки
Сортировать по одному Период недостаточно: если два документа записаны одним моментом времени, их строки перемешаются. Регистратор в сортировке убирает эту неоднозначность.
Определить тип документа, не делая соединения, помогает функция ТИПЗНАЧЕНИЯ: ТИПЗНАЧЕНИЯ(Движения.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг). Она пригодится в выражениях ВЫБОР КОГДА … ТОГДА, когда нужно пометить строки разных документов, не обращаясь к их таблицам.
Обратная задача — найти все движения одного документа — решается отбором по регистратору через параметр. В код запроса передают ссылку на документ:
ВЫБРАТЬ
Движения.Период,
Движения.Номенклатура,
Движения.ВидДвижения,
Движения.Количество
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Движения
ГДЕ
Движения.Регистратор = &Документ
И Движения.Активность
УПОРЯДОЧИТЬ ПО
Движения.НомерСтроки
Параметр &Документ устанавливается в коде: Запрос.УстановитьПараметр("Документ", СсылкаНаДокумент). Такой отбор работает по индексу и быстр даже на больших регистрах — это основной приём, когда нужно посмотреть, что именно записал конкретный документ.
Чтобы получить просто список документов, затронувших регистр за период, без строк движений, группируют по регистратору. Так удобно считать итог на каждый документ:
ВЫБРАТЬ
Движения.Регистратор,
СУММА(Движения.Количество) КАК Количество
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Движения
ГДЕ
Движения.Активность
И Движения.Период МЕЖДУ &Начало И &Конец
СГРУППИРОВАТЬ ПО
Движения.Регистратор
Группировать по составному полю можно напрямую — приведение типа здесь не нужно, потому что сравниваются ссылки, а не реквизиты документов.
Регистратор в виртуальных таблицах и срезах
Виртуальные таблицы — главная засада. Платформа агрегирует данные, и регистратор в части из них просто отсутствует.
| Виртуальная таблица | Поле Регистратор |
|---|---|
Остатки | нет (данные свёрнуты) |
Обороты | есть, если периодичность = Регистратор или Запись |
ОстаткиИОбороты | как у Обороты |
СрезПоследних / СрезПервых | есть (для подчинённого регистра) |
| Основная таблица движений | есть всегда |
Логика простая: в остатках регистратора быть не может — там сумма по многим документам сразу. Если регистратор нужен, берите либо основную таблицу движений, либо обороты с нужной периодичностью.
Для оборотов периодичность задаётся третьим параметром. Чтобы в результате появилось поле Регистратор, укажите Регистратор:
ВЫБРАТЬ
Обороты.Регистратор,
Обороты.Номенклатура,
Обороты.КоличествоОборот
ИЗ
РегистрНакопления.ТоварыНаСкладах.Обороты(
&НачалоПериода,
&КонецПериода,
Регистратор)
КАК Обороты
Для регистра сведений, подчинённого регистратору, срезы возвращают регистратор той записи, которая оказалась последней (или первой) в разрезе измерений:
ВЫБРАТЬ
Срез.Период,
Срез.Регистратор,
Срез.Номенклатура,
Срез.Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&НаДату, )
КАК Срез
Если тот же регистр сведений
независимый, конструктор запроса не покажет поле Регистратор ни в срезе, ни в основной таблице — и это не ошибка, а следствие режима записи.
У регистра бухгалтерии логика та же. В основной таблице и в виртуальной таблице ДвиженияССубконто регистратор есть, в Остатках — нет, в Оборотах — только с периодичностью Регистратор. Это удобно, когда нужно разложить обороты по счёту в разрезе документов, которые их сформировали:
ВЫБРАТЬ
Обороты.Регистратор,
Обороты.Счет,
Обороты.СуммаОборотДт,
Обороты.СуммаОборотКт
ИЗ
РегистрБухгалтерии.Хозрасчетный.Обороты(
&Начало, &Конец, Регистратор, , , , , )
КАК Обороты
Как получить реквизиты документа-регистратора
Часто нужен не сам документ, а его реквизиты: контрагент, организация, склад, договор. Обращаться через точку от составного поля — Движения.Регистратор.Контрагент — технически можно, но это приводит к соединению со всеми типами документов, у которых есть такой реквизит. О производительности ниже; пока — как делать правильно.
Приводите регистратор к конкретному типу оператором ВЫРАЗИТЬ. Платформа соединяется только с одной таблицей документов, а не со всеми сразу:
ВЫБРАТЬ
Движения.Регистратор,
ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент КАК Контрагент,
ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Склад КАК Склад
ИЗ
РегистрНакопления.Продажи КАК Движения
ГДЕ
Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
Для движений разных документов приведений будет несколько — по одному на каждый тип. Там, где тип регистратора другой, ВЫРАЗИТЬ вернёт NULL, поэтому значения часто собирают через функцию ЕСТЬNULL или объединяют несколько приведений.
Общие реквизиты документа — Дата, Номер, Проведен, ПометкаУдаления — есть у всех документов. К ним можно обратиться и напрямую (Движения.Регистратор.Дата), но именно это и создаёт соединение со всеми типами. Если выборка большая, лучше тоже приводить тип.
ВЫРАЗИТЬ не «фильтрует» строки — он только задаёт тип для получения реквизита. Чтобы в выборку не попали движения других документов, добавьте условие ССЫЛКА в секцию ГДЕ, как в примере выше.
Соединение движений с таблицей документов
Второй способ добраться до реквизитов — явное соединение таблицы движений с таблицей документа. Он удобен, когда реквизитов много или когда нужны табличные части документа.
ВЫБРАТЬ
Движения.Регистратор,
Реализация.Контрагент,
Реализация.Организация,
Реализация.ДоговорКонтрагента
ИЗ
РегистрНакопления.Продажи КАК Движения
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
ПО Движения.Регистратор = Реализация.Ссылка
ГДЕ
Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
Ключевой момент — условие соединения ПО Движения.Регистратор = Реализация.Ссылка. Соединяем составное поле регистра со ссылкой документа.
Когда в регистре движения делают несколько видов документов, на каждый вид делают отдельное соединение, а поля собирают через ЕСТЬNULL:
ВЫБРАТЬ
Движения.Регистратор,
ЕСТЬNULL(Реализация.Контрагент, Поступление.Контрагент) КАК Контрагент
ИЗ
РегистрНакопления.Продажи КАК Движения
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
ПО Движения.Регистратор = Реализация.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг КАК Поступление
ПО Движения.Регистратор = Поступление.Ссылка
Сравнивать ВЫРАЗИТЬ и соединение имеет смысл так:
| Задача | Чем брать |
|---|---|
| 1–2 простых реквизита, один тип документа | ВЫРАЗИТЬ |
| Много реквизитов или табличная часть | Явное СОЕДИНЕНИЕ |
| Несколько типов регистраторов | Соединения по каждому типу + ЕСТЬNULL |
Производительность: индексы и неявные соединения
Отбор по регистратору работает быстро: поле Регистратор входит в индексы таблицы движений, поэтому условие ГДЕ Регистратор = &Ссылка или ГДЕ Регистратор ССЫЛКА Документ.X отрабатывает по индексу. Это штатный и дешёвый сценарий — именно так платформа удаляет и перепроводит движения одного документа.
Главный тормоз в запросах с регистратором — неявные соединения по составному типу. Когда вы пишете Регистратор.Дата или Регистратор.Номер, платформа не знает заранее, какой это документ, и строит левое соединение с таблицей каждого типа, входящего в составной тип поля. Если регистратором могут быть полтора десятка документов — получите полтора десятка соединений, большая часть которых вернёт NULL.
Что с этим делать:
- 🎯 Приводите тип через
ВЫРАЗИТЬ— остаётся одно соединение вместо многих. - 🔎 Сужайте тип условием
ССЫЛКАвГДЕ, чтобы в выборку не попадали лишние документы. - 🧱 Для оборотов явно указывайте периодичность
Регистратор— не тяните регистратор из основной таблицы, если хватает агрегированных данных. - 📉 Не вызывайте реквизиты документа в секции
ГДЕбез ограничения типа: отбор поРегистратор.Контрагентпревратится в соединение со всеми документами ещё и на этапе фильтрации.
Проверить реальный план можно через технологический журнал или замер производительности в конфигураторе: в тексте SQL-запроса неявные соединения видны как цепочка LEFT JOIN к таблицам документов. Если их неожиданно много — ищите обращение к составному полю через точку.
Регистратор в последовательностях документов
У последовательностей (Последовательность) регистратор тоже есть — это документ, формирующий границу. Запросом можно получить и саму таблицу последовательности, и её границы.
Граница последовательности по измерениям берётся из виртуальной таблицы Границы:
ВЫБРАТЬ
Границы.Регистратор,
Границы.Период
ИЗ
Последовательность.ВзаиморасчетыПоставщиков.Границы КАК Границы
В основной таблице последовательности Регистратор указывает на документы, входящие в последовательность, а если у последовательности заданы измерения — рядом будут и они. Это удобно, когда нужно найти, с какого документа «поехала» последовательность и что перепроводить.
Тип поля здесь тот же составной ДокументСсылка, поэтому все правила выше действуют: реквизиты документа границы получайте через ВЫРАЗИТЬ, фильтр по виду документа — через ССЫЛКА.
Частые вопросы
Почему в запросе нет поля Регистратор?
Регистратор.Регистратор вернул NULL при обращении к реквизиту — в чём дело?
ВЫРАЗИТЬ к типу, которому строка не соответствует. Для нужного типа значение будет, для остальных — NULL. Соберите результат через ЕСТЬNULL.Как отфильтровать движения только одного вида документа?
ССЫЛКА: ГДЕ Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг. ВЫРАЗИТЬ сам по себе строки не отсекает — он только приводит тип.Что быстрее — ВЫРАЗИТЬ или соединение документа?
ВЫРАЗИТЬ компактнее, явное соединение удобнее, когда реквизитов много или нужна табличная часть. Главное — не обращаться к составному полю через точку без ограничения типа.Можно ли получить номер строки движения документа?
НомерСтроки — номер строки записи внутри документа. В виртуальной таблице оборотов оно появляется при периодичности Запись.