Как в СКД реализовать отбор по двум разным реквизитам через одно поле ввода?

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

При разработке отчетов на Системе компоновки данных (СКД) часто возникает задача предоставить пользователю максимально простой интерфейс. Одной из таких задач является поиск объекта сразу по нескольким критериям через одно поле. Например, нам нужно найти документ, в котором искомая Номенклатура указана либо в основном реквизите шапки, либо в любой строке табличной части СоставНоменклатуры. Рассмотрим подробно, как это реализовать различными способами, проанализируем нюансы работы с параметрами и расширением языка запросов.

Метод 1. Использование объединения в запросе (UNION)

Проанализируем ситуацию: если мы просто добавим условие ГДЕ для обоих полей, система будет искать совпадение одновременно в обоих местах (логическое "И"), что нам не подходит. Чтобы найти документы, подходящие под любое из условий, можно воспользоваться оператором ОБЪЕДИНИТЬ. Разберем пример реализации в тексте запроса набора данных:


ВЫБРАТЬ
    Документ.Ссылка КАК Ссылка
ИЗ
    Документ.ТестовыйДокумент КАК Документ
ГДЕ
    Документ.Номенклатура = &Номенклатура

ОБЪЕДИНИТЬ

ВЫБРАТЬ
    Состав.Ссылка КАК Ссылка
ИЗ
    Документ.ТестовыйДокумент.СоставНоменклатуры КАК Состав
ГДЕ
    Состав.Номенклатура = &Номенклатура

Рассмотрим, что здесь происходит. В первой части запроса мы выбираем документы, где нужная нам номенклатура стоит в шапке. Во второй части — документы, где она встречается в табличной части. Использование оператора ОБЪЕДИНИТЬ (без слова ВСЕ) автоматически удалит дубликаты, если одна и та же номенклатура оказалась и в шапке, и в таблице. Это самый надежный способ с точки зрения производительности базы данных при больших объемах информации.

Метод 2. Использование условия с логическим «ИЛИ» и проверка на пустое значение

Иногда переписывать структуру запроса через объединение неудобно (например, если запрос уже очень сложный). В этом случае мы можем прописать условие в секции ГДЕ, используя логику выбора. Выясним причину, почему обычное условие может работать некорректно: нам нужно учитывать ситуацию, когда пользователь оставил параметр пустым. Проанализируем пример кода:


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

В данном случае мы используем левое соединение с табличной частью. Это позволяет нам проверить наличие номенклатуры в строках. Важный момент: проверка &Номенклатура = ЗНАЧЕНИЕ(...) необходима, чтобы при незаполненном параметре отчет выводил все данные, а не пустой результат. Однако помните, что при соединении с табличной частью строки документа могут дублироваться, поэтому в итоговых настройках СКД или в самом запросе следует использовать ключевое слово РАЗЛИЧНЫЕ.

Метод 3. Группировка условий в пользовательских настройках (без кода)

Рассмотрим вариант, когда мы не хотим менять текст запроса. СКД позволяет гибко настраивать отборы в интерфейсе. Посмотрим, как это сделать по шагам:

  1. Перейдем на вкладку «Настройки», затем в раздел «Отбор».
  2. Нажмем правой кнопкой мыши и выберем пункт «Сгруппировать условия».
  3. В появившемся окне выберем тип группы «Группа ИЛИ».
  4. Внутри этой группы добавим два поля: Номенклатура (из шапки) и СоставНоменклатуры.Номенклатура.
  5. Чтобы пользователь не вводил значение дважды, установим для обоих полей один и тот же Параметр данных в колонке «Правое значение».

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

Метод 4. Использование фигурных скобок {ГДЕ ...}

Разберем продвинутый метод с использованием расширения языка запросов СКД. Это позволяет сделать условие «необязательным» на уровне SQL-запроса. Если пользователь не заполнил поле, СКД просто вырежет этот кусок из финального запроса к базе данных.


ВЫБРАТЬ
    ТестовыйДокумент.Ссылка
ИЗ
    Документ.ТестовыйДокумент КАК ТестовыйДокумент
{ГДЕ (ТестовыйДокумент.Номенклатура = &Номенклатура 
      ИЛИ ТестовыйДокумент.Ссылка В (
          ВЫБРАТЬ Ссылка 
          ИЗ Документ.ТестовыйДокумент.СоставНоменклатуры 
          ГДЕ Номенклатура = &Номенклатура
      ))}

Использование конструкции во вложенном запросе внутри {ГДЕ} позволяет эффективно фильтровать документы по табличным частям, избегая лишних соединений и дублирования строк в основном наборе данных.

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

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

Таким образом, мы проанализировали несколько подходов к решению задачи. Выбор конкретного метода зависит от сложности вашего отчета и требований к производительности. Для простых списков идеально подходит Группа ИЛИ в настройках, а для сложных аналитических отчетов лучше использовать ОБЪЕДИНИТЬ в тексте запроса.

← На главную