Как в запросе 1С выбрать товар по группе и избежать ошибок при соединении таблиц

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

При разработке отчетов и запросов в системе «1С:Предприятие 8» программисты часто сталкиваются с необходимостью отфильтровать данные не по конкретным элементам, а по целым папкам (группам) справочника. Типичный пример — получение данных о продажах всех товаров, входящих в категорию «Аксессуары». В этой статье мы подробно разберем, как правильно реализовать выборку по иерархии, настроить параметры запроса и избежать распространенных ошибок при соединении таблиц.

Использование оператора В ИЕРАРХИИ для фильтрации групп

Для того чтобы выбрать все элементы, принадлежащие определенному родителю (включая элементы во вложенных подпапках), в языке запросов 1С предусмотрен специальный оператор В ИЕРАРХИИ. Рассмотрим, чем он отличается от обычного сравнения.

Если мы напишем Номенклатура.Родитель = &Группа, запрос выберет только те товары, которые лежат непосредственно в указанной папке. Если внутри «Аксессуаров» есть подпапка «Чехлы», товары из нее в отчет не попадут. Чтобы захватить всю глубину вложения, мы используем конструкцию:


ГДЕ
    Номенклатура Ссылка В ИЕРАРХИИ(&Группа)

Важный нюанс: при установке значения параметра &Группа в коде или в консоли запросов необходимо убедиться, что тип параметра соответствует типу ссылки справочника (например, СправочникСсылка.Номенклатура). Если в интерфейсе выбора параметра вы не можете выбрать группу, проверьте настройки выбора — иногда там установлено ограничение «Выбирать только элементы».

Оптимизация запроса: фильтрация в виртуальных таблицах

Проанализируем ситуацию, когда нам нужно получить обороты из регистра накопления. Начинающие разработчики часто совершают ошибку, накладывая фильтр ГДЕ в самом конце запроса. Это заставляет систему сначала прочитать все записи регистра из базы данных, а потом отсеивать лишнее. Правильный подход — передача условий напрямую в параметры виртуальной таблицы.

Рассмотрим пример правильной передачи фильтра в виртуальную таблицу Продажи.Обороты:


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура,
    ПродажиОбороты.КоличествоОборот,
    ПродажиОбороты.СуммаОборот
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , Номенклатура В ИЕРАРХИИ (&Группа)) КАК ПродажиОбороты

В данном случае фильтр сработает на уровне СУБД еще при формировании выборки, что значительно ускорит выполнение запроса, особенно если база данных имеет большой объем.

Разбор ошибок при соединении таблиц

Часто в сложных запросах требуется объединить данные из справочников (например, список филиалов) и данные о продажах. Разберем типичную ошибку, которая часто встречается в коде:


// Ошибочный фрагмент
ПО втФилиал.Ссылка = ПродажиОбороты.Наименование

Выясним причину ошибки. В 1С нельзя сравнивать поля разных типов. Поле Ссылка имеет тип ссылки на объект, а Наименование — это строка. Такое соединение либо приведет к ошибке выполнения, либо всегда будет давать пустой результат.

Как сделать правильно: Соединение всегда должно происходить по полям одного типа. Если в регистре продаж есть измерение Филиал, то соединять нужно именно с ним:


ВЫБРАТЬ
    втФилиал.Наименование КАК ФилиалНаименование,
    СУММА(ПродажиОбороты.КоличествоОборот) КАК Кол
ИЗ
    втФилиал КАК втФилиал
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(,, , ) КАК ПродажиОбороты
    ПО втФилиал.Ссылка = ПродажиОбороты.Филиал
СГРУППИРОВАТЬ ПО
    втФилиал.Наименование

Работа с временными таблицами (ПОМЕСТИТЬ)

Использование временных таблиц — это «золотой стандарт» разработки в 1С. Это делает запрос читаемым и позволяет СУБД строить более эффективный план выполнения. Рассмотрим по шагам процесс создания и использования временной таблицы:

  1. Создание и заполнение: Мы выбираем нужные данные и используем ключевое слово ПОМЕСТИТЬ, присваивая таблице имя (например, втФилиалы).
  2. Разделитель: Обязательно используем символ «;» для разделения частей пакета запросов.
  3. Обращение: В последующих частях запроса мы обращаемся к втФилиалы как к обычной таблице.

Посмотрим на исправленный пример запроса из темы обсуждения:


ВЫБРАТЬ
    Филиалы.Ссылка КАК Ссылка,
    Филиалы.Наименование КАК Наименование
ПОМЕСТИТЬ втФилиалы
ИЗ
    Справочник.Филиалы КАК Филиалы
ГДЕ
    Филиалы.ЭтоГруппа = ЛОЖЬ;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ПродажиОбороты.Номенклатура.Родитель КАК КатегорияТовара,
    втФилиалы.Наименование КАК Филиал,
    СУММА(ПродажиОбороты.КоличествоОборот) КАК Количество
ИЗ
    втФилиалы КАК втФилиалы
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.Продажи.Обороты(,, , ) КАК ПродажиОбороты
    ПО втФилиалы.Ссылка = ПродажиОбороты.Филиал
ГДЕ
    ПродажиОбороты.Номенклатура В ИЕРАРХИИ(&ГруппаТоваров)
СГРУППИРОВАТЬ ПО
    ПродажиОбороты.Номенклатура.Родитель,
    втФилиалы.Наименование

Нюансы агрегатных функций: СРЕДНЕЕ vs СУММА

Проанализируем использование функции СРЕДНЕЕ(). Важно понимать, что в запросе СРЕДНЕЕ(СуммаПродажиОборот) вычислит среднее значение среди всех строк, попавших в выборку. Если ваша цель — получить средний чек, это сработает. Однако, если вы хотите получить «средние продажи в день», вам потребуется сначала сгруппировать данные по дням в одной временной таблице, а затем рассчитать среднее значение уже на основе этих итогов во втором запросе.

В большинстве задач по продажам за день, как в исходном запросе, правильнее использовать СУММА(), так как нам нужен общий оборот филиала по конкретной группе товаров.

Рекомендации по повышению производительности

Для того чтобы ваши запросы работали быстро даже на больших объемах данных, придерживайтесь следующих правил:

  1. Индексация: Если временная таблица содержит более нескольких десятков записей, индексируйте ее по полям, которые участвуют в соединениях (например, по полю Ссылка).
  2. Минимизация данных: Не выбирайте из базы лишние поля. Если вам нужно только наименование филиала для вывода, не тяните весь объект целиком.
  3. Иерархия в итогах: Если нужно построить древовидный отчет, рассмотрите возможность использования конструкции ИТОГИ ПО Номенклатура ИЕРАРХИЯ. Это встроенный механизм платформы, который автоматически рассчитает суммы для каждого уровня вложенности папок.

Таким образом, правильное использование оператора В ИЕРАРХИИ в сочетании с грамотной настройкой параметров виртуальных таблиц и контролем типов данных при соединениях позволяет создавать быстрые и надежные механизмы получения данных в 1С.

← На главную