При работе с данными бухгалтерского учета в 1С часто возникает необходимость извлечь информацию, которая не хранится непосредственно в регистрах бухгалтерии, а находится в связанных справочниках или регистрах сведений. Одним из таких типовых запросов является получение инвентарного номера основного средства (ОС), когда в качестве аналитики (субконто) выступает само ОС.
В типовых конфигурациях 1С, таких как "Бухгалтерия государственного учреждения" (БГУ) или "Бухгалтерия предприятия", инвентарный номер редко хранится как прямой реквизит справочника "Основные средства". Чаще всего он находится либо в отдельном подчиненном справочнике (например, Справочник.ИнвентарныеНомераОС), либо в регистре сведений, который фиксирует первоначальные или актуальные сведения об ОС (например, РегистрСведений.ПервоначальныеСведенияОСБухгалтерскийУчет).
Разберем подробно, как мы можем получить инвентарный номер в запросе, начиная с данных из виртуальных таблиц регистра бухгалтерии.
Начнем с анализа ситуации, когда вы пытаетесь напрямую обратиться к реквизиту инвентарного номера через Дт109Кт104.Субконто1.ИнвентарныйНомер и получаете NULL. Причина этого в том, что поля Субконто1, Субконто2, КорСубконто1 и т.д. в виртуальных таблицах регистра бухгалтерии (например, Обороты, Остатки) имеют составной тип. Это означает, что в них может храниться ссылка на объект любого справочника или документа, который определен для данного вида субконто на плане счетов.
Поскольку 1С не знает заранее, какой именно тип объекта хранится в конкретной строке поля Субконто1, она не может автоматически "подтянуть" реквизиты, специфичные для одного из этих типов. Чтобы получить доступ к реквизитам, нам необходимо явно указать системе, с каким типом мы собираемся работать. Для этого используется функция ВЫРАЗИТЬ.
Предположим, что в вашей конфигурации инвентарный номер хранится в отдельном справочнике Справочник.ИнвентарныеНомераОС, который содержит реквизит (например, ОС) со ссылкой на Справочник.ОсновныеСредства. Это распространенная модель в некоторых конфигурациях или доработках.
В вашем исходном запросе мы видим: ЕСТЬNULL(Дт109Кт104.КорСубконто1, ДтН25_Н26_КтН02.КорСубконто1) КАК ОсновноеСредство. Это указывает на то, что ссылка на Основное Средство находится в КорСубконто1. Мы будем работать именно с этим полем.
Функция ВЫРАЗИТЬ позволяет явно привести составной тип к конкретному типу справочника. Синтаксис выглядит так: ВЫРАЗИТЬ(<ПолеСоставногоТипа> КАК <ТипСправочника>). В нашем случае это будет ВЫРАЗИТЬ(Дт109Кт104.КорСубконто1 КАК Справочник.ОсновныеСредства).
После того как мы явно выразили КорСубконто1 как ссылку на Справочник.ОсновныеСредства, мы можем использовать эту ссылку для соединения с таблицей справочника инвентарных номеров. Используем ЛЕВОЕ СОЕДИНЕНИЕ, чтобы гарантировать, что все записи из нашей основной выборки сохранятся, даже если для какого-то ОС инвентарный номер не будет найден.
Предположим, что в Справочник.ИнвентарныеНомераОС есть реквизит ОС, который ссылается на Справочник.ОсновныеСредства.
ВЫБРАТЬ РАЗЛИЧНЫЕ
ЕСТЬNULL(Дт109Кт104.Субконто1, ДтН25_Н26_КтН02.Субконто1) КАК ВидЗатрат,
ЕСТЬNULL(Дт109Кт104.КорСубконто1, ДтН25_Н26_КтН02.КорСубконто1) КАК ОсновноеСредство,
ИнвентарныеНомераОС.Ссылка КАК ИнвентарныйНомер, // Получаем сам инвентарный номер
Дт109Кт104.Счет КАК СчетДт,
Дт109Кт104.КорСчет КАК СчетКт,
Дт109Кт104.СуммаОборотДт КАК Сумма,
ДтН25_Н26_КтН02.Счет КАК СчетДтНУ,
ДтН25_Н26_КтН02.КорСчет КАК СчетКтНУ,
ДтН25_Н26_КтН02.СуммаОборотДт КАК СуммаНУ
ПОМЕСТИТЬ ВТ_Амортизации
ИЗ
РегистрБухгалтерии.ЖурналПроводокЕПСБУ.Обороты(НАЧАЛОПЕРИОДА(&НачПериода, ДЕНЬ), КОНЕЦПЕРИОДА(&КонПериода, ДЕНЬ), Период, Счет В ИЕРАРХИИ (&СписокСчетов109), , КФО = &КФО, КорСчет В ИЕРАРХИИ (&СписокСчетов104), ) КАК Дт109Кт104
ПОЛНОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.ЖурналПроводокЕПСБУ.Обороты(НАЧАЛОПЕРИОДА(&НачПериода, ДЕНЬ), КОНЕЦПЕРИОДА(&КонПериода, ДЕНЬ), Период, Счет В ИЕРАРХИИ (&СписокСчетовН25_Н26), , , КорСчет В ИЕРАРХИИ (&СписокСчетовН02), ) КАК ДтН25_Н26_КтН02
ПО Дт109Кт104.КорСубконто1 = ДтН25_Н26_КтН02.КорСубконто1
И Дт109Кт104.Субконто1 = ДтН25_Н26_КтН02.Субконто1
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ИнвентарныеНомераОС КАК ИнвентарныеНомераОС
ПО ВЫРАЗИТЬ(ЕСТЬNULL(Дт109Кт104.КорСубконто1, ДтН25_Н26_КтН02.КорСубконто1) КАК Справочник.ОсновныеСредства) = ИнвентарныеНомераОС.ОС
;
Важные моменты:
ВЫРАЗИТЬ(ЕСТЬNULL(Дт109Кт104.КорСубконто1, ДтН25_Н26_КтН02.КорСубконто1) КАК Справочник.ОсновныеСредства): Здесь мы сначала используем ЕСТЬNULL, чтобы получить Основное Средство из одной из двух таблиц оборотов (либо БУ, либо НУ), а затем явно выражаем его как Справочник.ОсновныеСредства. Это критически важно для корректного соединения.ИнвентарныеНомераОС.Ссылка КАК ИнвентарныйНомер: Мы выбираем саму ссылку на элемент справочника ИнвентарныеНомераОС, который по умолчанию содержит номер в своем представлении или коде. Если инвентарный номер - это реквизит, то нужно указывать ИнвентарныеНомераОС.КакойТоРеквизит.ЛЕВОЕ СОЕДИНЕНИЕ: Это гарантирует, что мы не потеряем записи из нашего основного набора данных (обороты по амортизации), даже если для какого-либо ОС инвентарный номер не был найден в справочнике ИнвентарныеНомераОС. В таком случае поле ИнвентарныйНомер будет NULL.Если в вашем справочнике ИнвентарныеНомераОС инвентарный номер хранится не в коде или наименовании, а в отдельном реквизите, например, Номер, то вместо ИнвентарныеНомераОС.Ссылка мы будем выбирать ИнвентарныеНомераОС.Номер.
В современных типовых конфигурациях 1С (например, БГУ 2.0 или БП 3.0) инвентарные номера и другие важные сведения об ОС часто хранятся в регистрах сведений, таких как РегистрСведений.ПервоначальныеСведенияОСБухгалтерскийУчет. Этот подход является более гибким, так как регистры сведений позволяют хранить историю изменений этих данных. Для получения актуальных данных на определенную дату мы будем использовать "срез последних" регистра сведений.
Как и в предыдущем решении, мы используем ВЫРАЗИТЬ(ЕСТЬNULL(Дт109Кт104.КорСубконто1, ДтН25_Н26_КтН02.КорСубконто1) КАК Справочник.ОсновныеСредства), чтобы получить ссылку на Основное Средство.
Виртуальная таблица СрезПоследних регистра сведений позволяет получить актуальные данные по всем измерениям на заданную дату. Она принимает два основных параметра: дату среза и (опционально) отбор по измерениям. В нашем случае это будет дата окончания периода запроса (&КонПериода) и отбор по измерению ОсновноеСредство.
ВЫБРАТЬ РАЗЛИЧНЫЕ
ЕСТЬNULL(Дт109Кт104.Субконто1, ДтН25_Н26_КтН02.Субконто1) КАК ВидЗатрат,
ЕСТЬNULL(Дт109Кт104.КорСубконто1, ДтН25_Н26_КтН02.КорСубконто1) КАК ОсновноеСредство,
ПервоначальныеСведенияОСБухгалтерскийУчетСрезПоследних.ИнвентарныйНомер КАК ИнвентарныйНомер, // Получаем инвентарный номер из регистра
Дт109Кт104.Счет КАК СчетДт,
Дт109Кт104.КорСчет КАК СчетКт,
Дт109Кт104.СуммаОборотДт КАК Сумма,
ДтН25_Н26_КтН02.Счет КАК СчетДтНУ,
ДтН25_Н26_КтН02.КорСчет КАК СчетКтНУ,
ДтН25_Н26_КтН02.СуммаОборотДт КАК СуммаНУ
ПОМЕСТИТЬ ВТ_Амортизации
ИЗ
РегистрБухгалтерии.ЖурналПроводокЕПСБУ.Обороты(НАЧАЛОПЕРИОДА(&НачПериода, ДЕНЬ), КОНЕЦПЕРИОДА(&КонПериода, ДЕНЬ), Период, Счет В ИЕРАРХИИ (&СписокСчетов109), , КФО = &КФО, КорСчет В ИЕРАРХИИ (&СписокСчетов104), ) КАК Дт109Кт104
ПОЛНОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.ЖурналПроводокЕПСБУ.Обороты(НАЧАЛОПЕРИОДА(&НачПериода, ДЕНЬ), КОНЕЦПЕРИОДА(&КонПериода, ДЕНЬ), Период, Счет В ИЕРАРХИИ (&СписокСчетовН25_Н26), , , КорСчет В ИЕРАРХИИ (&СписокСчетовН02), ) КАК ДтН25_Н26_КтН02
ПО Дт109Кт104.КорСубконто1 = ДтН25_Н26_КтН02.КорСубконто1
И Дт109Кт104.Субконто1 = ДтН25_Н26_КтН02.Субконто1
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПервоначальныеСведенияОСБухгалтерскийУчет.СрезПоследних(
&КонПериода,
ОсновноеСредство В
(ВЫБРАТЬ РАЗЛИЧНЫЕ ВЫРАЗИТЬ(ЕСТЬNULL(Дт109Кт104.КорСубконто1, ДтН25_Н26_КтН02.КорСубконто1) КАК Справочник.ОсновныеСредства)
ИЗ РегистрБухгалтерии.ЖурналПроводокЕПСБУ.Обороты(НАЧАЛОПЕРИОДА(&НачПериода, ДЕНЬ), КОНЕЦПЕРИОДА(&КонПериода, ДЕНЬ), Период, Счет В ИЕРАРХИИ (&СписокСчетов109), , КФО = &КФО, КорСчет В ИЕРАРХИИ (&СписокСчетов104), ) КАК ВложенныйДт109Кт104
ПОЛНОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.ЖурналПроводокЕПСБУ.Обороты(НАЧАЛОПЕРИОДА(&НачПериода, ДЕНЬ), КОНЕЦПЕРИОДА(&КонПериода, ДЕНЬ), Период, Счет В ИЕРАРХИИ (&СписокСчетовН25_Н26), , , КорСчет В ИЕРАРХИИ (&СписокСчетовН02), ) КАК ВложенныйДтН25_Н26_КтН02
ПО ВложенныйДт109Кт104.КорСубконто1 = ВложенныйДтН25_Н26_КтН02.КорСубконто1
И ВложенныйДт109Кт104.Субконто1 = ВложенныйДтН25_Н26_КтН02.Субконто1)
) КАК ПервоначальныеСведенияОСБухгалтерскийУчетСрезПоследних
ПО ВЫРАЗИТЬ(ЕСТЬNULL(Дт109Кт104.КорСубконто1, ДтН25_Н26_КтН02.КорСубконто1) КАК Справочник.ОсновныеСредства) = ПервоначальныеСведенияОСБухгалтерскийУчетСрезПоследних.ОсновноеСредство
;
Пояснения к срезу последних:
СрезПоследних(&КонПериода, ОсновноеСредство В (...)): Здесь &КонПериода - это параметр, который передает дату, на которую нам нужны актуальные данные. Вложенный запрос (ВЫБРАТЬ РАЗЛИЧНЫЕ ...) позволяет нам отобрать только те Основные Средства, которые присутствуют в наших проводках, что существенно оптимизирует производительность запроса, поскольку нам не нужно получать срез по всем ОС, а только по релевантным.ПервоначальныеСведенияОСБухгалтерскийУчетСрезПоследних.ИнвентарныйНомер: Мы обращаемся к ресурсу ИнвентарныйНомер регистра сведений, где хранится нужное нам значение. Название ресурса может отличаться в вашей конфигурации.РегистрСведений.МестонахождениеОС. Всегда проверяйте структуру вашей конкретной конфигурации.При составлении подобных запросов, особенно затрагивающих большие объемы данных из регистров бухгалтерии, следует придерживаться нескольких правил:
ВЫРАЗИТЬ вы не сможете получить доступ к реквизитам.ЛЕВОЕ СОЕДИНЕНИЕ: Если данные из внешней таблицы (справочника или регистра сведений) не являются обязательными для каждой строки основной выборки, используйте ЛЕВОЕ СОЕДИНЕНИЕ. Это позволяет сохранить все строки из основной таблицы, даже если соответствующей записи во внешней таблице не найдено.НАЧАЛОПЕРИОДА, КОНЕЦПЕРИОДА), списка счетов (Счет В ИЕРАРХИИ) и других измерений прямо в виртуальные таблицы регистров бухгалтерии и срезов регистров сведений. Это позволяет 1С выбирать только необходимый объем данных на уровне СУБД, что значительно повышает производительность.СрезПоследних, если вы фильтруете его по измерению (например, ОсновноеСредство В (...)), это помогает получить только релевантные данные. Если не фильтровать, 1С может построить срез по всем существующим ОС, что может быть очень долго.ИЗ) была та, которая дает наибольший объем данных и содержит основные сущности, по которым строится отчет. В вашем случае это таблицы оборотов регистра бухгалтерии. Если сделать основной таблицу справочника ИнвентарныеНомераОС, это может привести к нежелательному утяжелению запроса и избыточной выборке данных, как вы наблюдали в своих попытках.ИнвентарныеНомераОС.ОС), действительно имеет тип СправочникСсылка.ОсновныеСредства и соответствует типу выраженного субконто.Таким образом, для успешного получения инвентарного номера из субконто в запросе 1С необходимо четко понимать, как он хранится в вашей конфигурации, и использовать соответствующие механизмы запросов, такие как ВЫРАЗИТЬ для приведения типов и ЛЕВОЕ СОЕДИНЕНИЕ со справочниками или регистрами сведений.