Почему отбор "Номенклатура.Наименование содержит" не работает в отчетах на СКД в 1С:Управление торговлей 11 и как это исправить?

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

При работе с отчетами на системе компоновки данных (СКД) в конфигурации 1С:Управление торговлей 11, мы можем столкнуться с ситуацией, когда стандартный отбор по строковому полю, например, "Номенклатура.Наименование содержит", не дает ожидаемых результатов. Это может привести к тому, что отчеты не фильтруются должным образом, несмотря на то, что искомое значение точно присутствует в наименованиях номенклатуры. В этой статье мы подробно разберем, почему такая проблема возникает, и предложим надежные способы ее решения.

Проблема отбора "Содержит" в СКД: Анализируем ситуацию

Оператор "Содержит" в СКД предназначен для поиска подстроки в текстовом поле и по своей сути аналогичен оператору ПОДОБНО (LIKE) в языке запросов 1С, который автоматически добавляет символы процента (%) в начале и конце строки шаблона для частичного совпадения (например, %искомое_значение%). Однако, несмотря на кажущуюся простоту, этот механизм может давать сбои в сложных отчетах, особенно в конфигурациях типа УТ11, где часто используются пакетные запросы с множеством временных таблиц, различных соединений и функций.

Мы выяснили, что причина некорректной работы отбора "Содержит" может крыться в нескольких факторах:

  1. Сложность структуры запроса: Если схема компоновки данных использует пакетные запросы с несколькими временными таблицами, левыми соединениями (ЛЕВОЕ СОЕДИНЕНИЕ) или функциями типа ЕСТЬNULL, автоматический механизм СКД может некорректно применить условие отбора к финальному результату или к промежуточным таблицам.
  2. Неявное указание таблицы: В некоторых случаях, когда поле с одним и тем же именем (например, Номенклатура) присутствует в нескольких наборах данных или источниках, СКД может неверно определить, к какому именно полю следует применить отбор.
  3. Особенности генерации запроса СКД: Автоматическая генерация запроса компоновщиком макета компоновки данных не всегда идеально справляется с очень сложными сценариями, что может приводить к тому, что условие отбора либо не попадает в итоговый запрос, либо применяется не к тому источнику данных.
  4. Тип данных поля и индексация: Хотя Наименование обычно является строковым полем, иногда нюансы его представления или отсутствие нужных индексов в базе данных могут влиять на производительность и корректность работы оператора поиска.

В нашем случае, искомое значение (например, "22") точно присутствовало в поле Номенклатура.Наименование, но стандартный отбор через настройки СКД не работал. Это указывает на то, что проблема лежит глубже, чем просто ошибка во вводимых данных или поиск по неправильному полю.

Решение 1: Перенос отбора в текст запроса СКД (Рекомендуемый подход)

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

Разберем по шагам, как это сделать:

  1. Откроем схему компоновки данных. В конфигураторе или режиме 1С:Предприятие (через "Все функции" -> "Стандартные" -> "Изменить схему компоновки данных") откроем схему компоновки данных нашего отчета.

  2. Найдем основной набор данных. Перейдем на вкладку "Наборы данных" и выберем тот набор данных, который формирует основные данные для отчета и содержит поле Номенклатура.Наименование.

  3. Изменим текст запроса. Нажмем кнопку "Конструктор запроса" или непосредственно в поле "Текст запроса" внесем изменения.

  4. Добавим условие ПОДОБНО в предложение ГДЕ. Мы используем оператор ПОДОБНО и явным образом формируем маску поиска. Рассмотрим следующий пример, основанный на запросе из нашей темы:

    
    ВЫБРАТЬ
        втЗаказыСКомплектующимиОсновная.Заказ КАК Заказ,
        втЗаказыСКомплектующимиОсновная.ДатаОплаты КАК ДатаОплаты,
        втЗаказыСКомплектующимиОсновная.Номенклатура КАК Номенклатура,
        втЗаказыСКомплектующимиОсновная.Количество КАК Количество,
        втЗаказыСКомплектующимиОсновная.НоменклатураКомплектующая КАК НоменклатураКомплектующая,
        втЗаказыСКомплектующимиОсновная.КоличествоКомплектующие КАК КоличествоКомплектующие,
        ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
        ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) * втЗаказыСКомплектующимиОсновная.КоличествоКомплектующие КАК Сумма,
        втЗаказыСКомплектующимиОсновная.Заказ.Менеджер КАК ЗаказМенеджер
    ИЗ
        втЗаказыСКомплектующимиОсновная КАК втЗаказыСКомплектующимиОсновная
            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних
            ПО втЗаказыСКомплектующимиОсновная.НоменклатураКомплектующая = ЦеныНоменклатурыСрезПоследних.Номенклатура
    ГДЕ
        ЦеныНоменклатурыСрезПоследних.ВидЦены = &ВидЦены
        И втЗаказыСКомплектующимиОсновная.Номенклатура.Наименование ПОДОБНО "%" + ВЫРАЗИТЬ(&НаименованиеДляОтбора КАК СТРОКА(100)) + "%"
    

    В этом примере мы добавили строку: И втЗаказыСКомплектующимиОсновная.Номенклатура.Наименование ПОДОБНО "%" + ВЫРАЗИТЬ(&НаименованиеДляОтбора КАК СТРОКА(100)) + "%". Здесь:

    • втЗаказыСКомплектующимиОсновная.Номенклатура.Наименование – это полный путь к полю Наименование номенклатуры, участвующей в отчете. Важно указывать полный путь к полю из того источника, откуда мы хотим брать наименование.
    • ПОДОБНО – оператор для поиска по маске.
    • "%" + ВЫРАЗИТЬ(&НаименованиеДляОтбора КАК СТРОКА(100)) + "%" – это шаблон поиска. Мы берем значение из параметра СКД &НаименованиеДляОтбора, преобразуем его к строковому типу с заданной длиной (СТРОКА(100) для надежности) и обрамляем символами процента %, которые означают "любая последовательность символов" до и после искомой подстроки.
  5. Объясняем ВЫРАЗИТЬ(&НаименованиеДляОтбора КАК СТРОКА(100)). Функция ВЫРАЗИТЬ используется для явного приведения параметра к строковому типу с указанием максимальной длины. Это важно для корректной работы оператора ПОДОБНО, особенно если параметр может быть изначально другого типа или иметь неограниченную длину, что иногда вызывает проблемы с производительностью или совместимостью с СУБД.

  6. Настроим параметр. После добавления параметра &НаименованиеДляОтбора в текст запроса, нам необходимо объявить его на вкладке "Параметры" схемы СКД. Укажем для него тип "Строка" и, при необходимости, установим значение по умолчанию или настроим доступность для пользователя в настройках отчета.

  7. Удалим стандартный отбор. Если до этого мы пытались настроить отбор "Номенклатура.Наименование содержит" на вкладке "Отборы" схемы СКД или в пользовательских настройках, его следует удалить, чтобы избежать дублирования или конфликтов.

Преимущества данного подхода: Полный контроль над логикой отбора, надежность и предсказуемость, так как условие отбора напрямую встраивается в запрос, выполняемый СУБД.

Решение 2: Явное указание таблицы для отбора (Менее универсальный подход)

В некоторых случаях, как нам подсказали в сообщении 2, может помочь явное указание таблицы, к которой должен относиться отбор по номенклатуре. Этот подход актуален, когда в отчете используются несколько наборов данных, или одно и то же поле (например, Номенклатура) фигурирует в разных соединениях. В СКД это обычно реализуется путем точного указания пути к полю в настройках отбора, например, НаборДанных1.Номенклатура.Наименование вместо просто Номенклатура.Наименование.

Чтобы применить этот подход, мы должны:

  1. Открыть настройки отчета (или схему СКД).
  2. Перейти на вкладку "Отборы".
  3. Добавить новый элемент отбора.
  4. В поле "Поле" (или "Путь к данным") не просто выбрать Номенклатура.Наименование, а найти его в дереве доступных полей, обращая внимание на его родительский элемент (например, НаборДанных1.Номенклатура.Наименование, или полное имя временной таблицы и ее поля, как втЗаказыСКомплектующимиОсновная.Номенклатура.Наименование, если СКД позволяет это настроить через интерфейс).
  5. Выбрать вид сравнения "Содержит" и указать нужное значение.

Этот метод может сработать, если проблема заключалась в неоднозначности ссылки на поле для СКД. Однако, как показывает практика, для сложных пакетных запросов, этот способ менее надежен, чем прямое встраивание условия в текст запроса.

Анализ причины: Сложность пакетных запросов и соединений

Для более глубокого понимания проблемы, рассмотрим предоставленный в сообщении 12 текст запроса. Он представляет собой пакетный запрос, использующий несколько временных таблиц (втЗаказыСДатойПервойОплаты, втЗаказыСНоменклатурой, втЗаказыСКомплектующимиОсновная) и разнообразные соединения, включая ЛЕВОЕ СОЕДИНЕНИЕ. Также активно используются функции ЕСТЬNULL и агрегатные функции (СУММА, МАКСИМУМ, МИНИМУМ).

При таком уровне сложности, автоматический механизм СКД, который пытается перевести пользовательские отборы в предложения ГДЕ или ИМЕЮЩИЕ запроса, может столкнуться со следующими трудностями:

Когда мы настраиваем отбор в пользовательском режиме или в схеме СКД, компоновщик макета компоновки данных анализирует структуру запроса и пытается оптимально встроить условия фильтрации. Однако, в случае сложного пакетного запроса, он может "запутаться" и применить отбор не так, как мы ожидаем. Это приводит к тому, что отчеты, как мы видим, "не чувствуют" нашего отбора "содержит", даже если данные присутствуют.

Рекомендации по отладке

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

  1. Использование консоли запросов. Создайте простой запрос в консоли запросов 1С, который выбирает только поле Номенклатура.Наименование и применяет к нему условие ПОДОБНО "%искомое_значение%". Это позволит нам убедиться, что сам оператор ПОДОБНО с нашим значением работает корректно на уровне базы данных.

    
    ВЫБРАТЬ
        СправочникНоменклатура.Наименование
    ИЗ
        Справочник.Номенклатура КАК СправочникНоменклатура
    ГДЕ
        СправочникНоменклатура.Наименование ПОДОБНО "%22%"
    
  2. Проверка сформированного запроса СКД. В конструкторе СКД, на вкладке "Наборы данных", после настройки отбора (даже если он не работает) нажмите кнопку "Запрос". СКД покажет итоговый запрос, который будет отправлен в СУБД. Внимательно изучите этот запрос. Есть ли в нем ваше условие отбора? В каком предложении (ГДЕ или ИМЕЮЩИЕ) оно находится? К какому полю оно применяется? Это поможет нам выявить расхождения между тем, что мы хотим, и тем, что генерирует СКД.

Анализируя сформированный СКД запрос, мы часто можем увидеть, что отбор по Номенклатура.Наименование содержит либо отсутствует, либо применяется к некорректному источнику данных, либо находится в таком месте запроса, что не дает нужного эффекта из-за логики соединений или агрегации.

Заключение

Проблема с некорректной работой отбора "содержит" в отчетах на СКД, особенно в сложных конфигурациях вроде УТ11, является достаточно распространенной. Мы рассмотрели, что это происходит из-за особенностей автоматического формирования запросов СКД при наличии пакетных запросов, временных таблиц и различных типов соединений. Наиболее эффективным и надежным решением является перенос логики отбора непосредственно в текст запроса схемы компоновки данных с использованием оператора ПОДОБНО и явным формированием маски поиска. Это дает нам полный контроль над процессом фильтрации и обеспечивает предсказуемый результат работы отчета.

← На главную