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

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

Как получить регистратор в запросе 1С

Как получить регистратор в запросе 1С: обращение к полю Регистратор, отбор движений по документу, виртуальные таблицы, типовые ошибки и примеры кода запросов.

Регистратор — это документ, который сформировал записи в регистре накопления, сведений, бухгалтерии или расчёта. В запросах 1С получить регистратора нужно в двух типовых ситуациях: когда из строки регистра требуется выйти на документ-источник и его реквизиты, и когда наоборот — по документу нужно выбрать все его движения. Оба сценария решаются штатными средствами языка запросов без обходов выборки в коде.

Ключевой момент: поле «Регистратор» присутствует в физических таблицах регистров и содержит ссылку на документ. Через точку от него доступны реквизиты документа — номер, дата, организация, контрагент и любые другие. При этом важно понимать, какие таблицы содержат это поле, а в каких виртуальных таблицах (остатки, обороты) регистратор недоступен по определению.

Что такое регистратор и где хранится это поле

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

В тексте запроса к полю обращаются по имени «Регистратор» через псевдоним таблицы. Поскольку документы-регистраторы могут быть разных типов (например, «ПоступлениеТоваров» и «РеализацияТоваров» одновременно), поле имеет составной тип. Это влияет на соединения и сравнения: платформа умеет работать с составными ссылками, но неявные соединения по ним могут выполняться медленнее, чем по однотипным.

Как выбрать регистратора из таблицы регистра

Базовый запрос к физической таблице регистра накопления выглядит так: указываете поле «Регистратор» в списке выбираемых полей и при необходимости разворачиваете его реквизиты через точку. Разворачивание через точку на самом деле порождает левое соединение с таблицей документа, что платформа делает автоматически.

ВЫБРАТЬ

Движения.Регистратор КАК Документ,

Движения.Регистратор.Номер КАК НомерДокумента,

Движения.Регистратор.Дата КАК ДатаДокумента,

Движения.Номенклатура КАК Номенклатура,

Движения.Количество КАК Количество

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Движения

ГДЕ

Движения.Период МЕЖДУ &НачалоПериода И &КонецПериода

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

Как отобрать движения по конкретному документу

Обратная задача — получить все записи регистра, сформированные конкретным документом. Для этого в секции ГДЕ поле «Регистратор» сравнивают с параметром-ссылкой. Параметр удобно передавать через метод УстановитьПараметр объекта запроса.

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

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

"ВЫБРАТЬ

| Движения.Номенклатура КАК Номенклатура,

| Движения.Количество КАК Количество

|ИЗ

| РегистрНакопления.ТоварыНаСкладах КАК Движения

|ГДЕ

| Движения.Регистратор = &Регистратор";

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

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

Такой отбор эффективен: по полю «Регистратор» в таблице регистра существует индекс, поэтому выборка движений одного документа выполняется быстро даже на больших объёмах. Именно этот приём используется в типовых механизмах — например, при восстановлении движений документа или при проверке, проводился ли документ по регистру.

Порядок действий
  1. 1
    Определите, из какого регистра нужны движения и есть ли у него подчинение регистратору
  2. 2
    Напишите запрос к физической таблице регистра с полем Регистратор
  3. 3
    Для отбора по документу добавьте условие ГДЕ Регистратор = &Регистратор и передайте ссылку параметром
  4. 4
    Для чтения реквизитов документа разверните поле через точку или примените ВЫРАЗИТЬ
  5. 5
    Выполните запрос и проверьте результат в консоли запросов на тестовых данных

Регистратор в виртуальных таблицах: ограничения

Виртуальные таблицы «Остатки», «Обороты», «ОстаткиИОбороты» агрегируют данные, поэтому поле «Регистратор» в них либо отсутствует, либо появляется только при определённых настройках. В таблице «Обороты» регистратор доступен, если включить периодичность «Регистратор» — тогда обороты группируются по каждому документу отдельно. В таблице «Остатки» регистратора нет в принципе: остаток не привязан к одному документу.

Если нужен список документов, изменивших остаток за период, корректный путь — запрос к физической таблице с группировкой по регистратору или виртуальная таблица «Обороты» с периодичностью «Регистратор»:

ВЫБРАТЬ

Обороты.Регистратор КАК Документ,

Обороты.КоличествоОборот КАК Оборот

ИЗ

РегистрНакопления.ТоварыНаСкладах.Обороты(

&НачалоПериода, &КонецПериода, Регистратор, ) КАК Обороты

Третий параметр виртуальной таблицы здесь задаёт периодичность «Регистратор». Четвёртый параметр — условие — оставлен пустым, но туда можно передать отбор, например по номенклатуре, чтобы сократить объём вычислений.

Соединение регистра с документом и типовые ошибки

Явное соединение с таблицей документа нужно, когда требуются реквизиты, недоступные через точку, или когда соединяемся с табличной частью документа. Соединение выполняют по условию равенства ссылки документа полю «Регистратор». При составном типе регистратора соединяться следует с конкретной таблицей документа и комбинировать результаты через ОБЪЕДИНИТЬ ВСЕ, если регистраторов несколько видов.

Распространённые ошибки при работе с регистратором в запросах:

Типичные ошибки
01
Обращение к полю Регистратор у независимого регистра сведений — запрос падает с ошибкой, такого поля там нет
02
Ожидание регистратора в таблице Остатки — там его нет по определению, нужна таблица Обороты с периодичностью Регистратор
03
Сравнение регистратора со строкой или числом вместо ссылки — параметр должен быть ссылкой на документ
04
Соединение по составному регистратору без приведения типа — лишние строки и медленный план запроса
05
Разворачивание через точку множества реквизитов — каждое обращение порождает соединение, лучше одно явное соединение с таблицей документа

Ещё одна тонкость: у частично проведённого или распроведённого документа записей в регистре может не быть, поэтому соединение «от регистра к документу» безопаснее, чем «от документа к регистру» с внутренним соединением — во втором случае документы без движений просто выпадут из выборки. Если нужны и такие документы, используйте левое соединение от таблицы документа к регистру.

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

Проверку удобно выполнять в консоли запросов на копии базы. Контрольные признаки корректности: количество строк движений по документу совпадает с данными кнопки «Движения» в форме документа; ссылки регистратора не пустые; реквизиты документа через точку совпадают с данными формы. Если запрос возвращает NULL в реквизитах регистратора — проверьте, не смешаны ли в выборке документы разных типов.

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

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

Совпадение с движениями документа
Норма

Набор строк запроса совпадает со списком движений из формы документа

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

Строк больше или меньше — проверьте отбор по регистратору и периоду

Заполненность реквизитов регистратора
Норма

Номер и дата документа выводятся для всех строк

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

NULL в реквизитах — составной тип регистратора, нужно ВЫРАЗИТЬ

Скорость выполнения
Норма

Запрос по одному документу выполняется мгновенно

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

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

Если в отчёте регистратор нужен только для расшифровки, не выводите реквизиты документа через точку в основном запросе — передайте саму ссылку, а реквизиты получайте в расшифровке. Это заметно разгружает запрос на больших регистрах.
ПЗ
Практическое замечание
Итог

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

Регистратор доступен в физических таблицах регистров, подчинённых регистратору, через поле «Регистратор». Для отбора движений документа используйте ГДЕ Регистратор = &Ссылка, для реквизитов — обращение через точку или ВЫРАЗИТЬ, а в виртуальных таблицах помните про ограничения: в остатках регистратора нет, в оборотах он появляется только с периодичностью «Регистратор».

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

Можно ли получить регистратора в запросе к независимому регистру сведений?

Нет. У независимого регистра сведений поля «Регистратор» не существует, и запрос с таким полем завершится ошибкой. Если связь с документом нужна, добавьте в регистр собственный реквизит типа «ДокументСсылка» и заполняйте его при записи.

Почему реквизит регистратора через точку возвращает NULL?

Чаще всего потому, что поле «Регистратор» имеет составной тип, а запрошенный реквизит есть не у всех видов документов. Для несовместимых типов платформа возвращает NULL. Используйте ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.НужныйВид) — тогда реквизит будет заполнен для документов нужного вида.

Как получить список документов, которые делали движения по регистру за период?

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

Что быстрее: обращение к реквизитам регистратора через точку или явное соединение?

Обращение через точку платформа преобразует в левое соединение автоматически, поэтому для одного-двух реквизитов разницы нет. Если нужно много реквизитов, одно явное соединение с таблицей документа читается лучше и даёт платформе более понятную структуру запроса.

Как проверить в запросе, проводился ли документ по регистру?

Выполните запрос с условием ГДЕ Регистратор = &Ссылка и проверьте, пуст ли результат: Если Запрос.Выполнить().Пустой() Тогда — движений нет. Это надёжнее, чем анализировать признак «Проведен» документа, так как документ может быть проведён, но не делать движений по конкретному регистру.

Можно ли в параметр запроса передать список регистраторов?

Да. Передайте массив или список значений со ссылками и используйте условие Движения.Регистратор В (&СписокДокументов). Для больших списков эффективнее поместить ссылки во временную таблицу и соединиться с ней.