При работе с отчетами на системе компоновки данных (СКД) в конфигурации 1С:Управление торговлей 11, мы можем столкнуться с ситуацией, когда стандартный отбор по строковому полю, например, "Номенклатура.Наименование содержит", не дает ожидаемых результатов. Это может привести к тому, что отчеты не фильтруются должным образом, несмотря на то, что искомое значение точно присутствует в наименованиях номенклатуры. В этой статье мы подробно разберем, почему такая проблема возникает, и предложим надежные способы ее решения.
Оператор "Содержит" в СКД предназначен для поиска подстроки в текстовом поле и по своей сути аналогичен оператору ПОДОБНО (LIKE) в языке запросов 1С, который автоматически добавляет символы процента (%) в начале и конце строки шаблона для частичного совпадения (например, %искомое_значение%). Однако, несмотря на кажущуюся простоту, этот механизм может давать сбои в сложных отчетах, особенно в конфигурациях типа УТ11, где часто используются пакетные запросы с множеством временных таблиц, различных соединений и функций.
Мы выяснили, что причина некорректной работы отбора "Содержит" может крыться в нескольких факторах:
ЛЕВОЕ СОЕДИНЕНИЕ) или функциями типа ЕСТЬNULL, автоматический механизм СКД может некорректно применить условие отбора к финальному результату или к промежуточным таблицам.Номенклатура) присутствует в нескольких наборах данных или источниках, СКД может неверно определить, к какому именно полю следует применить отбор.Наименование обычно является строковым полем, иногда нюансы его представления или отсутствие нужных индексов в базе данных могут влиять на производительность и корректность работы оператора поиска.В нашем случае, искомое значение (например, "22") точно присутствовало в поле Номенклатура.Наименование, но стандартный отбор через настройки СКД не работал. Это указывает на то, что проблема лежит глубже, чем просто ошибка во вводимых данных или поиск по неправильному полю.
Наиболее надежным и часто рекомендуемым способом решения подобных проблем является перенос логики отбора непосредственно в текст основного запроса схемы компоновки данных. Этот подход дает нам полный контроль над тем, как будет выполняться фильтрация.
Откроем схему компоновки данных. В конфигураторе или режиме 1С:Предприятие (через "Все функции" -> "Стандартные" -> "Изменить схему компоновки данных") откроем схему компоновки данных нашего отчета.
Найдем основной набор данных. Перейдем на вкладку "Наборы данных" и выберем тот набор данных, который формирует основные данные для отчета и содержит поле Номенклатура.Наименование.
Изменим текст запроса. Нажмем кнопку "Конструктор запроса" или непосредственно в поле "Текст запроса" внесем изменения.
Добавим условие ПОДОБНО в предложение ГДЕ. Мы используем оператор ПОДОБНО и явным образом формируем маску поиска. Рассмотрим следующий пример, основанный на запросе из нашей темы:
ВЫБРАТЬ
втЗаказыСКомплектующимиОсновная.Заказ КАК Заказ,
втЗаказыСКомплектующимиОсновная.ДатаОплаты КАК ДатаОплаты,
втЗаказыСКомплектующимиОсновная.Номенклатура КАК Номенклатура,
втЗаказыСКомплектующимиОсновная.Количество КАК Количество,
втЗаказыСКомплектующимиОсновная.НоменклатураКомплектующая КАК НоменклатураКомплектующая,
втЗаказыСКомплектующимиОсновная.КоличествоКомплектующие КАК КоличествоКомплектующие,
ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) * втЗаказыСКомплектующимиОсновная.КоличествоКомплектующие КАК Сумма,
втЗаказыСКомплектующимиОсновная.Заказ.Менеджер КАК ЗаказМенеджер
ИЗ
втЗаказыСКомплектующимиОсновная КАК втЗаказыСКомплектующимиОсновная
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних
ПО втЗаказыСКомплектующимиОсновная.НоменклатураКомплектующая = ЦеныНоменклатурыСрезПоследних.Номенклатура
ГДЕ
ЦеныНоменклатурыСрезПоследних.ВидЦены = &ВидЦены
И втЗаказыСКомплектующимиОсновная.Номенклатура.Наименование ПОДОБНО "%" + ВЫРАЗИТЬ(&НаименованиеДляОтбора КАК СТРОКА(100)) + "%"
В этом примере мы добавили строку: И втЗаказыСКомплектующимиОсновная.Номенклатура.Наименование ПОДОБНО "%" + ВЫРАЗИТЬ(&НаименованиеДляОтбора КАК СТРОКА(100)) + "%". Здесь:
втЗаказыСКомплектующимиОсновная.Номенклатура.Наименование – это полный путь к полю Наименование номенклатуры, участвующей в отчете. Важно указывать полный путь к полю из того источника, откуда мы хотим брать наименование.ПОДОБНО – оператор для поиска по маске."%" + ВЫРАЗИТЬ(&НаименованиеДляОтбора КАК СТРОКА(100)) + "%" – это шаблон поиска. Мы берем значение из параметра СКД &НаименованиеДляОтбора, преобразуем его к строковому типу с заданной длиной (СТРОКА(100) для надежности) и обрамляем символами процента %, которые означают "любая последовательность символов" до и после искомой подстроки.Объясняем ВЫРАЗИТЬ(&НаименованиеДляОтбора КАК СТРОКА(100)). Функция ВЫРАЗИТЬ используется для явного приведения параметра к строковому типу с указанием максимальной длины. Это важно для корректной работы оператора ПОДОБНО, особенно если параметр может быть изначально другого типа или иметь неограниченную длину, что иногда вызывает проблемы с производительностью или совместимостью с СУБД.
Настроим параметр. После добавления параметра &НаименованиеДляОтбора в текст запроса, нам необходимо объявить его на вкладке "Параметры" схемы СКД. Укажем для него тип "Строка" и, при необходимости, установим значение по умолчанию или настроим доступность для пользователя в настройках отчета.
Удалим стандартный отбор. Если до этого мы пытались настроить отбор "Номенклатура.Наименование содержит" на вкладке "Отборы" схемы СКД или в пользовательских настройках, его следует удалить, чтобы избежать дублирования или конфликтов.
Преимущества данного подхода: Полный контроль над логикой отбора, надежность и предсказуемость, так как условие отбора напрямую встраивается в запрос, выполняемый СУБД.
В некоторых случаях, как нам подсказали в сообщении 2, может помочь явное указание таблицы, к которой должен относиться отбор по номенклатуре. Этот подход актуален, когда в отчете используются несколько наборов данных, или одно и то же поле (например, Номенклатура) фигурирует в разных соединениях. В СКД это обычно реализуется путем точного указания пути к полю в настройках отбора, например, НаборДанных1.Номенклатура.Наименование вместо просто Номенклатура.Наименование.
Чтобы применить этот подход, мы должны:
Номенклатура.Наименование, а найти его в дереве доступных полей, обращая внимание на его родительский элемент (например, НаборДанных1.Номенклатура.Наименование, или полное имя временной таблицы и ее поля, как втЗаказыСКомплектующимиОсновная.Номенклатура.Наименование, если СКД позволяет это настроить через интерфейс).Этот метод может сработать, если проблема заключалась в неоднозначности ссылки на поле для СКД. Однако, как показывает практика, для сложных пакетных запросов, этот способ менее надежен, чем прямое встраивание условия в текст запроса.
Для более глубокого понимания проблемы, рассмотрим предоставленный в сообщении 12 текст запроса. Он представляет собой пакетный запрос, использующий несколько временных таблиц (втЗаказыСДатойПервойОплаты, втЗаказыСНоменклатурой, втЗаказыСКомплектующимиОсновная) и разнообразные соединения, включая ЛЕВОЕ СОЕДИНЕНИЕ. Также активно используются функции ЕСТЬNULL и агрегатные функции (СУММА, МАКСИМУМ, МИНИМУМ).
При таком уровне сложности, автоматический механизм СКД, который пытается перевести пользовательские отборы в предложения ГДЕ или ИМЕЮЩИЕ запроса, может столкнуться со следующими трудностями:
ЛЕВОГО СОЕДИНЕНИЯ, если оно не было найдено (и, следовательно, стало NULL), может работать некорректно. Например, NULL-значение никогда не "содержит" какую-либо строку, что может привести к потере данных, если отбор должен был срабатывать только для существующих значений.ЕСТЬNULL: Использование ЕСТЬNULL для полей, по которым идет отбор, также усложняет анализ для СКД, поскольку она должна учесть, что поле может менять свое значение на основе условий.Когда мы настраиваем отбор в пользовательском режиме или в схеме СКД, компоновщик макета компоновки данных анализирует структуру запроса и пытается оптимально встроить условия фильтрации. Однако, в случае сложного пакетного запроса, он может "запутаться" и применить отбор не так, как мы ожидаем. Это приводит к тому, что отчеты, как мы видим, "не чувствуют" нашего отбора "содержит", даже если данные присутствуют.
Чтобы понять, что именно происходит с отбором, когда он не работает, мы рекомендуем следующие шаги отладки:
Использование консоли запросов. Создайте простой запрос в консоли запросов 1С, который выбирает только поле Номенклатура.Наименование и применяет к нему условие ПОДОБНО "%искомое_значение%". Это позволит нам убедиться, что сам оператор ПОДОБНО с нашим значением работает корректно на уровне базы данных.
ВЫБРАТЬ
СправочникНоменклатура.Наименование
ИЗ
Справочник.Номенклатура КАК СправочникНоменклатура
ГДЕ
СправочникНоменклатура.Наименование ПОДОБНО "%22%"
Проверка сформированного запроса СКД. В конструкторе СКД, на вкладке "Наборы данных", после настройки отбора (даже если он не работает) нажмите кнопку "Запрос". СКД покажет итоговый запрос, который будет отправлен в СУБД. Внимательно изучите этот запрос. Есть ли в нем ваше условие отбора? В каком предложении (ГДЕ или ИМЕЮЩИЕ) оно находится? К какому полю оно применяется? Это поможет нам выявить расхождения между тем, что мы хотим, и тем, что генерирует СКД.
Анализируя сформированный СКД запрос, мы часто можем увидеть, что отбор по Номенклатура.Наименование содержит либо отсутствует, либо применяется к некорректному источнику данных, либо находится в таком месте запроса, что не дает нужного эффекта из-за логики соединений или агрегации.
Проблема с некорректной работой отбора "содержит" в отчетах на СКД, особенно в сложных конфигурациях вроде УТ11, является достаточно распространенной. Мы рассмотрели, что это происходит из-за особенностей автоматического формирования запросов СКД при наличии пакетных запросов, временных таблиц и различных типов соединений. Наиболее эффективным и надежным решением является перенос логики отбора непосредственно в текст запроса схемы компоновки данных с использованием оператора ПОДОБНО и явным формированием маски поиска. Это дает нам полный контроль над процессом фильтрации и обеспечивает предсказуемый результат работы отчета.