В практике разработки на платформе 1С часто возникает задача собрать воедино информацию из нескольких различных бизнес-процессов или задач. Например, когда необходимо вывести в одну таблицу «Задачи на согласование бюджета», «Задачи по выбору поставщика» и «Задачи по договорам». Поскольку это разные объекты метаданных, простое обращение к одной таблице невозможно. В рамках данной статьи мы разберем, как правильно построить запрос для объединения данных, как корректно передать параметры из формы и как реализовать гибкую фильтрацию по статусу выполнения.
Проанализируем типичную ошибку начинающих разработчиков. Часто при попытке собрать данные из разных таблиц используется ЛЕВОЕ СОЕДИНЕНИЕ. Однако этот подход в корне неверен для данной задачи. Соединение предназначено для «склеивания» строк по горизонтали (добавление новых колонок к существующей записи), а нам нужно добавить строки по вертикали (собрать записи из разных таблиц в один список).
Использование соединений в данном контексте приводит к тому, что запрос становится тяжелым, нечитаемым и, что самое важное, он начинает множить количество колонок (Автор1, Автор2, Автор3), что крайне неудобно для вывода в одну таблицу. Правильным решением здесь является использование конструкции ОБЪЕДИНИТЬ ВСЕ (UNION ALL).
Рассмотрим, как правильно структурировать запрос. Основное правило при использовании ОБЪЕДИНИТЬ ВСЕ заключается в том, что количество и порядок колонок, а также их типы в каждом блоке ВЫБРАТЬ должны совпадать. Это позволит системе корректно сформировать итоговую таблицу.
Разберем пример запроса, который собирает данные из трех разных типов задач:
ВЫБРАТЬ
НА_ЗадачаСогласованияВыбораПоставщика.БизнесПроцесс.Автор КАК Автор,
НА_ЗадачаСогласованияВыбораПоставщика.БизнесПроцесс.Предмет КАК Предмет,
НА_ЗадачаСогласованияВыбораПоставщика.Дата КАК Дата,
НА_ЗадачаСогласованияВыбораПоставщика.Наименование КАК Наименование,
НА_ЗадачаСогласованияВыбораПоставщика.ДатаВыполнения КАК ДатаВыполнения,
НА_ЗадачаСогласованияВыбораПоставщика.Выполнена КАК Выполнена,
НА_ЗадачаСогласованияВыбораПоставщика.Исполнитель КАК Исполнитель
ИЗ
Задача.НА_ЗадачаСогласованияВыбораПоставщика КАК НА_ЗадачаСогласованияВыбораПоставщика
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
НА_ЗадачаСогласования.БизнесПроцесс.Автор,
НА_ЗадачаСогласования.БизнесПроцесс.Предмет,
НА_ЗадачаСогласования.Дата,
НА_ЗадачаСогласования.Наименование,
НА_ЗадачаСогласования.ДатаВыполнения,
НА_ЗадачаСогласования.Выполнена,
НА_ЗадачаСогласования.Исполнитель
ИЗ
Задача.НА_ЗадачаСогласования КАК НА_ЗадачаСогласования
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
НА_СогласованиеЗаказаПоставщику.БизнесПроцесс.Автор,
НА_СогласованиеЗаказаПоставщику.БизнесПроцесс.Предмет,
НА_СогласованиеЗаказаПоставщику.Дата,
НА_СогласованиеЗаказаПоставщику.Наименование,
НА_СогласованиеЗаказаПоставщику.ДатаВыполнения,
НА_СогласованиеЗаказаПоставщику.Выполнена,
НА_СогласованиеЗаказаПоставщику.Исполнитель
ИЗ
Задача.НА_СогласованиеЗаказаПоставщику КАК НА_СогласованиеЗаказаПоставщику
Обратите внимание: мы задаем псевдонимы колонок (через КАК) только в первом блоке выбора. Остальные блоки автоматически подстроятся под эти имена. Также важно помнить, что обращение Задача.БизнесПроцесс.Автор является обращением «через точку». Платформа 1С в этом случае автоматически выполнит неявное левое соединение с таблицей бизнес-процесса. Если база данных содержит сотни тысяч записей, это может снизить производительность, но для небольших и средних объемов это допустимый и наиболее наглядный способ.
Выясним причину, по которой запрос может выдавать пустой результат или игнорировать фильтры. В обычном интерфейсе 1С (8.1/8.2/8.3 в режиме обычного приложения) при обращении к реквизиту формы, например ЭлементыФормы.Исполнитель, мы получаем объект управления (поле ввода), а не само значение, которое в него введено.
Для того чтобы передать в запрос ссылку на пользователя, необходимо использовать свойство .Значение. Посмотрим на правильный пример установки параметров:
Запрос = Новый Запрос;
// Получаем ссылку на пользователя из элемента формы
ИсполнительСсылка = ЭлементыФормы.Исполнитель.Значение;
// Устанавливаем параметры запроса
Запрос.УстановитьПараметр("Исполнитель", ИсполнительСсылка);
Если пропустить .Значение, система попытается сравнить поле Исполнитель в базе данных (которое является ссылкой) с объектом формы, и условие ГДЕ никогда не выполнится.
Проанализируем задачу: нам нужно, чтобы при установленном флажке «Выполнено» выводились только завершенные задачи, а при снятом — абсолютно все задачи (и выполненные, и активные).
Многие разработчики пытаются использовать конструкцию ЕСЛИ... ТОГДА в коде 1С для формирования текста запроса, но это делает код громоздким. Элегантнее решить эту задачу внутри самого SQL-запроса с помощью логического условия в секции ГДЕ.
Рассмотрим логическую конструкцию: (&ВсеЗадачи ИЛИ Задача.Выполнена).
Если параметр &ВсеЗадачи равен ИСТИНА, то всё условие целиком становится истинным для любой строки (так как используется оператор ИЛИ), и фильтр по полю Выполнена фактически игнорируется. Если же &ВсеЗадачи равен ЛОЖЬ, то результат будет зависеть только от того, что находится в поле Задача.Выполнена.
Внимание: В коде из обсуждения автор использовал обратную логику (флаг назывался «Выполнено», но логика была как у «Все задачи»). Давайте напишем итоговый вариант кода с правильной фильтрацией:
// Предположим, на форме есть флажок "ТолькоВыполненные" (Булево)
ТолькоВыполненные = ЭлементыФормы.ФлажокТолькоВыполненные.Значение;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Исполнитель", ЭлементыФормы.Исполнитель.Значение);
Запрос.УстановитьПараметр("ПоказыватьВсе", НЕ ТолькоВыполненные);
Запрос.Текст =
"ВЫБРАТЬ
| Т.БизнесПроцесс.Автор КАК Автор,
| Т.БизнесПроцесс.Предмет КАК Предмет,
| Т.Дата КАК Дата,
| Т.Наименование КАК Наименование,
| Т.ДатаВыполнения КАК ДатаВыполнения
|ИЗ
| Задача.НА_ЗадачаСогласования КАК Т
|ГДЕ
| Т.Исполнитель = &Исполнитель
| И (&ПоказыватьВсе ИЛИ Т.Выполнена = ИСТИНА)
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Т.БизнесПроцесс.Автор,
| Т.БизнесПроцесс.Предмет,
| Т.Дата,
| Т.Наименование,
| Т.ДатаВыполнения
|ИЗ
| Задача.НА_ЗадачаСогласованияВыбораПоставщика КАК Т
|ГДЕ
| Т.Исполнитель = &Исполнитель
| И (&ПоказыватьВсе ИЛИ Т.Выполнена = ИСТИНА)";
// Выгружаем результат в табличное поле на форме
РезультатЗапроса = Запрос.Выполнить();
ТаблицаРезультата = РезультатЗапроса.Выгрузить();
// Если используется табличное поле "Список"
ЭлементыФормы.Список.СоздатьКолонки();
Список = ТаблицаРезультата; // Привязка данных
Для успешного создания отчета по задачам во внешней обработке мы выполнили следующие действия:
ОБЪЕДИНИТЬ ВСЕ для объединения данных из разных таблиц в один плоский список..Значение.ГДЕ для управления фильтрацией без динамической сборки текста запроса.Рекомендация: При работе с задачами в крупных конфигурациях (например, 1С:Документооборот) старайтесь также проверять адресацию. Задачи могут быть назначены не лично пользователю, а его роли. В таком случае вместо прямого сравнения Исполнитель = &Исполнитель может потребоваться соединение с регистром сведений АдресацияИсполнителей или использование виртуальных таблиц задач (если они предусмотрены для данных объектов).