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