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