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