При разработке отчетов и запросов в платформе 1С разработчики часто сталкиваются с ситуацией, когда необходимо получить остатки по регистру накопления и одновременно вывести определенное дополнительное поле (реквизит). Однако при обращении к виртуальной таблице Остатки нужного реквизита в списке полей просто оказывается нет. Проанализируем, почему платформа 1С накладывает такое ограничение и какими способами можно правильно решить эту техническую задачу.
Разберем архитектуру хранения данных в платформе 1С. Физически регистр накопления состоит из нескольких таблиц в СУБД, ключевыми из которых являются:
Период, Регистратор, ВидДвижения, Измерения, Ресурсы и Реквизиты.Измерений и Периода (с заданной периодичностью).Рассмотрим наглядный пример, демонстрирующий бессмысленность поиска реквизита в остатках. Предположим, по объекту Номенклатура ("Товар А") были выполнены две записи регистра:
Измерение = "Товар А", Ресурс = 10 шт., Реквизит = "Поступление №1"Измерение = "Товар А", Ресурс = 4 шт., Реквизит = "Реализация №1"В виртуальной таблице Остатки платформа рассчитывает итоговый результат по измерению "Товар А", который равен 6 шт. Реквизит является характеристикой отдельной записи, а не совокупного итога. На уровне остатка невозможно определить, какое именно значение из двух записей должен содержать реквизит. По этой причине платформа 1С принципиально не содержит реквизиты в таблицах итогов и виртуальных таблицах остатков.
Если задача состоит в том, чтобы рассчитывать и хранить остатки в разрезе этого поля, значит, на этапе проектирования структуры базы данных была допущена архитектурная ошибка. Реквизит необходимо перенести в состав измерений регистра.
Выполним следующие шаги для изменения структуры:
Измерение с нужным типом данных.После того как поле станет измерением, оно появится в виртуальной таблице Остатки, и по нему можно будет свободно получать остатки в запросах.
Если изменять структуру метаданных нельзя или поле требуется выводить исключительно как справочную информацию из последней поставки/движения, применим левое соединение с реальной таблицей регистра или с подзапросом.
Рассмотрим пример запроса, в котором извлекаются остатки и с помощью соединения с физической таблицей движений выбирается реквизит последнего движения по каждой позиции:
ВЫБРАТЬ
ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
ТоварыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток,
ПоследниеДвижения.РеквизитЗаписи КАК РеквизитЗаписи
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ
Движения.Номенклатура КАК Номенклатура,
МАКСИМУМ(Движения.РеквизитЗаписи) КАК РеквизитЗаписи
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Движения
ГРУППИРОВАТЬ ПО
Движения.Номенклатура
) КАК ПоследниеДвижения
ПО ТоварыНаСкладахОстатки.Номенклатура = ПоследниеДвижения.Номенклатура
Важно: При левом соединении с физической таблицей регистра без использования группировки и функции МАКСИМУМ (или среза по максимальной дате) существует риск задвоения строк в результате запроса, если по одному измерению существует несколько движений с разным содержимым реквизита.
Посмотрим на альтернативные варианты архитектурного решения задачи, когда делить остатки на уровне СУБД не требуется, но дополнительное поле необходимо в отчетах:
Номенклатура или СерииНоменклатуры. В запросе к таблице остатков такое поле легко вытягивается через точку: Номенклатура.СтранаПроисхождения.РегистрСведений. В запросе соединяйте виртуальную таблицу остатков регистра накопления с виртуальной таблицей СрезПоследних регистра сведений.