Как выбрать записи регистра, если в табличной части заказа есть определенный товар?

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

В процессе разработки отчетов или обработок в 1С:Управление нашей фирмой часто возникает задача отфильтровать данные по содержимому табличных частей документов. Например, нам нужно получить записи из регистра сведений, опираясь на то, есть ли в заказе покупателя, привязанном к записи, конкретная номенклатурная позиция.

Разберем основные подходы к решению этой задачи, рассмотрим примеры запросов и проанализируем, какой способ лучше подходит для различных ситуаций.

Решение через оператор «В»

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

Этот метод хорошо читается и удобен, если отбор по номенклатуре является простым условием:


ВЫБРАТЬ
    ЗаданияНаРаботу.ЗаказПокупателя
ИЗ
    РегистрСведений.ЗаданияНаРаботу КАК ЗаданияНаРаботу
ГДЕ
    ЗаданияНаРаботу.ЗаказПокупателя В (
        ВЫБРАТЬ РАЗЛИЧНЫЕ
            Товары.Ссылка
        ИЗ
            Документ.ЗаказПокупателя.Товары КАК Товары
        ГДЕ
            Товары.Номенклатура = &Товар1
    )

Важное замечание: При использовании оператора В убедитесь, что вы используете РАЗЛИЧНЫЕ или группировку во вложенном запросе, чтобы избежать дублирования записей, если товар встречается в одном заказе несколько раз.

Решение через внутреннее соединение (INNER JOIN)

Более производительным вариантом, особенно при работе с большими объемами данных, является использование ВНУТРЕННЕГО СОЕДИНЕНИЯ. При таком подходе СУБД получает возможность оптимизировать план выполнения запроса, объединяя таблицы на этапе их чтения.

Разберем пример реализации этого способа:


ВЫБРАТЬ РАЗЛИЧНЫЕ
    ЗаданияНаРаботу.ЗаказПокупателя
ИЗ
    РегистрСведений.ЗаданияНаРаботу КАК ЗаданияНаРаботу
ВНУТРЕННЕЕ СОЕДИНЕНИЕ 
    Документ.ЗаказПокупателя.Товары КАК ЗаказПокупателяТовары
ПО 
    ЗаданияНаРаботу.ЗаказПокупателя = ЗаказПокупателяТовары.Ссылка
ГДЕ
    ЗаказПокупателяТовары.Номенклатура = &Товар

Этот подход предпочтительнее в большинстве случаев, так как он позволяет платформе 1С эффективнее использовать индексы. Соединение по полю Ссылка табличной части и измерению регистра — это стандартная операция, которая работает быстро при наличии правильной индексации в базе данных.

Рекомендации по оптимизации запросов

Чтобы ваши отчеты и обработки работали максимально быстро, примите во внимание следующие советы:

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

В завершение, проанализируем ситуацию: если вам нужно просто выбрать записи из регистра, внутреннее соединение будет наиболее универсальным и быстрым решением. Если же структура запроса предполагает дальнейшее использование этих данных в других соединениях, смело используйте временные таблицы для повышения читаемости и производительности кода.

← На главную