В процессе разработки в среде 1С часто возникает задача: получить список комплектующих для конкретной продукции (спецификацию) и дополнить этот список актуальными ценами из регистра сведений. Начинающие разработчики часто сталкиваются с дублированием строк, синтаксическими ошибками при обращении к табличным частям и неверным отображением данных. В этой статье мы подробно разберем, как построить оптимальный запрос, избегая типичных ловушек.
Одной из главных трудностей, описанных в обсуждении, является ошибка: «В условиях соединения запроса не допускается обращение к табличным частям». Проанализируем ситуацию: когда мы пытаемся соединить основную таблицу справочника Справочник.Спецификации с другой таблицей, используя поле вложенной табличной части Состав, платформа выдает ошибку. Это происходит потому, что табличная часть — это отдельная подчиненная таблица БД.
Чтобы избежать этой ошибки, мы должны выбирать данные не из «шапки» справочника, а напрямую из таблицы его состава. Рассмотрим правильную структуру источника данных:
ВЫБРАТЬ
СпецификацииСостав.Номенклатура КАК Комплектующее,
СпецификацииСостав.Количество КАК Количество,
СпецификацииСостав.Ссылка.Владелец КАК Продукция
ИЗ
Справочник.Спецификации.Состав КАК СпецификацииСостав
ГДЕ
СпецификацииСостав.Ссылка.Владелец = &СсылкаНаПродукцию
Именно такое обращение позволяет нам работать с каждой строкой состава спецификации индивидуально, что является фундаментом для дальнейшего соединения с ценами.
Если мы выполним ЛЕВОЕ СОЕДИНЕНИЕ с физической таблицей регистра сведений РегистрСведений.ЦеныНоменклатуры, мы получим серьезную проблему: для каждого комплектующего в результат попадут все цены, которые когда-либо устанавливались в системе. Это приведет к тому, что одна позиция в отчете размножится на десятки строк.
Выясним причину: регистры цен являются периодическими. Физическая таблица хранит историю. Для получения одной актуальной цены нам необходимо использовать виртуальную таблицу СрезПоследних. Посмотрим, как это изменить в запросе:
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК ЦеныНоменклатуры
ПО СпецификацииСостав.Номенклатура = ЦеныНоменклатуры.Номенклатура
Использование СрезПоследних гарантирует, что для каждой номенклатуры будет найдена только одна запись, актуальная на указанную дату (параметр &Период).
Зачастую в базе ведется учет нескольких видов цен: оптовые, розничные, закупочные. Если не указать конкретный тип, запрос снова может выдать несколько строк на одну позицию (по одной строке для каждого вида цены). Разберем по шагам, как это реализовать в параметрах виртуальной таблицы:
СрезПоследних укажем условие: ВидЦены = &ВидЦены.Характеристика.ЕСТЬNULL, чтобы вместо пустых значений для позиций без цены выводился ноль.Проанализируем итоговый код запроса, который решает все поставленные задачи (отладить его можно, используя Консоль запросов для управляемых форм 8.3):
ВЫБРАТЬ
СпецификацииСостав.Ссылка.Наименование КАК СпецификацияНаименование,
СпецификацииСостав.Номенклатура КАК Номенклатура,
СпецификацииСостав.Номенклатура.Представление КАК НоменклатураПредставление,
СпецификацииСостав.Количество КАК Количество,
ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) КАК Цена,
ЕСТЬNULL(ЦеныНоменклатуры.Цена, 0) * СпецификацииСостав.Количество КАК Сумма
ИЗ
Справочник.Спецификации.Состав КАК СпецификацииСостав
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &ВидЦены) КАК ЦеныНоменклатуры
ПО СпецификацииСостав.Номенклатура = ЦеныНоменклатуры.Номенклатура
ГДЕ
СпецификацииСостав.Ссылка.Владелец = &НоменклатураВладелец
Для более сложных задач, когда спецификаций много или требуется дополнительная обработка данных, рекомендуется использовать временные таблицы. Это делает запрос более читаемым и упрощает отладку в консоли запросов. Рассмотрим этот метод:
Сначала выберем состав во временную таблицу:
ВЫБРАТЬ
СпецификацииСостав.Номенклатура КАК Номенклатура,
СпецификацииСостав.Количество КАК Количество
ПОМЕСТИТЬ ВТ_Состав
ИЗ
Справочник.Спецификации.Состав КАК СпецификацииСостав
ГДЕ
СпецификацииСостав.Ссылка.Владелец = &НоменклатураВладелец
;
Затем соединим полученную временную таблицу с актуальными ценами (для работы с текстами таких запросов удобен Процессор схемы запроса):
ВЫБРАТЬ
ВТ_Состав.Номенклатура КАК Номенклатура,
ВТ_Состав.Количество КАК Количество,
ЕСТЬNULL(Цены.Цена, 0) КАК Цена
ИЗ
ВТ_Состав КАК ВТ_Состав
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ВидЦены = &ВидЦены) КАК Цены
ПО ВТ_Состав.Номенклатура = Цены.Номенклатура
Как было отмечено в сообщениях форума, часто причиной неработоспособности запроса являются банальные опечатки. Обратим внимание на несколько критических моментов:
ВЫБРАТЬ должно отделяться запятой. Перед ключевым словом ИЗ запятая не ставится.Подводя итог, можно сказать, что корректная работа с составом продукции требует четкого понимания структуры таблиц 1С. Всегда используйте виртуальные таблицы для получения цен и не забывайте про фильтрацию по виду цен, чтобы избежать дублей. Такой подход обеспечит высокую скорость работы системы и достоверность получаемых данных.