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