При разработке в среде 1С:Предприятие часто возникает задача анализа связанных объектов. Одним из наиболее эффективных инструментов для этого являются Критерии отбора. Однако стандартный запрос к критерию отбора, такому как СвязанныеДокументы, возвращает разнородный список всех документов, которые входят в состав этого критерия. Это могут быть и заказы, и реализации, и счета, и акты. Рассмотрим подробнее, как из этого массива данных выделить именно те документы, которые нам необходимы для решения конкретной бизнес-задачи.
Представим ситуацию: мы обращаемся к виртуальной таблице критерия отбора, чтобы найти документы, связанные с определенным объектом (например, договором или заказом). Наш исходный запрос выглядит следующим образом:
ВЫБРАТЬ
СвязанныеДокументы.Ссылка КАК Ссылка
ИЗ
КритерийОтбора.СвязанныеДокументы(&Значение1) КАК СвязанныеДокументы
ГДЕ
СвязанныеДокументы.Ссылка.Проведен
Этот запрос вернет нам все проведенные документы, связанные с параметром &Значение1. Если в системе настроено много связей, список может быть огромным. Наша цель — оставить в выборке только документы определенного вида, например, Документ.РезервированиеТоваров.
Часто разработчики пытаются применить проверку типа прямо в списке выбора (секция ВЫБРАТЬ). Проанализируем, к чему это приводит:
ВЫБРАТЬ
СвязанныеДокументы.Ссылка ССЫЛКА Документ.РезервированиеТоваров КАК ЭтоРезервирование
ИЗ
КритерийОтбора.СвязанныеДокументы(&Значение1) КАК СвязанныеДокументы
В данном случае оператор ССЫЛКА вернет логическое значение (Булево): Истина, если документ является резервированием, и Ложь в противном случае. Сама ссылка на документ при этом не фильтруется, и мы получаем список из "Да" и "Нет", что не решает нашу задачу получения конкретного объекта.
Для того чтобы ограничить выборку на уровне СУБД и получить только нужные нам документы, необходимо перенести условие проверки типа в секцию ГДЕ. Выясним причину, почему это важно: платформа 1С транслирует такой запрос в SQL-код, который эффективно отсекает ненужные таблицы еще на этапе выполнения запроса к базе данных.
Рассмотрим правильный пример кода:
ВЫБРАТЬ
СвязанныеДокументы.Ссылка КАК Ссылка
ИЗ
КритерийОтбора.СвязанныеДокументы(&Значение1) КАК СвязанныеДокументы
ГДЕ
СвязанныеДокументы.Ссылка ССЫЛКА Документ.РезервированиеТоваров
И СвязанныеДокументы.Ссылка.Проведен
Здесь мы четко указываем системе: "Выбери только те ссылки, тип которых соответствует документу Резервирование товаров". Это самый быстрый и правильный способ фильтрации по типу в языке запросов 1С.
После того как мы отфильтровали документы, нам часто нужно получить их специфические реквизиты. Например, у документа РезервированиеТоваров есть реквизит Склад, которого нет у других связанных документов. Если мы просто напишем Ссылка.Склад, система может выполнить неоптимальное соединение со всеми таблицами. Посмотрим на пример использования функции ВЫРАЗИТЬ:
ВЫБРАТЬ
ВЫРАЗИТЬ(СвязанныеДокументы.Ссылка КАК Документ.РезервированиеТоваров).Склад КАК Склад,
СвязанныеДокументы.Ссылка КАК Ссылка
ИЗ
КритерийОтбора.СвязанныеДокументы(&Значение1) КАК СвязанныеДокументы
ГДЕ
СвязанныеДокументы.Ссылка ССЫЛКА Документ.РезервированиеТоваров
Использование ВЫРАЗИТЬ помогает системе жестко типизировать поле. Это не только позволяет обращаться к реквизитам конкретного типа, но и повышает производительность, так как оптимизатор запросов точно знает, к какой физической таблице обращаться за данными.
Иногда требуется получить документы не одного, а двух или трех видов (например, все первичные документы реализации и акты). В этом случае мы используем логический оператор ИЛИ в условии:
ГДЕ
(СвязанныеДокументы.Ссылка ССЫЛКА Документ.РеализацияТоваровУслуг
ИЛИ СвязанныеДокументы.Ссылка ССЫЛКА Документ.АктВыполненныхРабот)
Важный момент: не забывайте про скобки, если у вас есть другие условия (например, проверка на проведение или пометку удаления), чтобы логика И и ИЛИ отработала корректно.
Если ваша задача — выбрать из множества связанных документов только один (например, последний созданный), проанализируем ситуацию с использованием конструкций ПЕРВЫЕ и УПОРЯДОЧИТЬ ПО. Без сортировки запрос может вернуть любую случайную запись, подходящую под условия.
ВЫБРАТЬ ПЕРВЫЕ 1
СвязанныеДокументы.Ссылка КАК Ссылка
ИЗ
КритерийОтбора.СвязанныеДокументы(&Значение1) КАК СвязанныеДокументы
ГДЕ
СвязанныеДокументы.Ссылка ССЫЛКА Документ.РезервированиеТоваров
УПОРЯДОЧИТЬ ПО
СвязанныеДокументы.Ссылка.Дата УБЫВ
В данном примере мы получим самый свежий документ резервирования, связанный с нашим объектом.
Нам важно понимать, что КритерийОтбора — это виртуальная таблица. На уровне СУБД она представляет собой объединение (UNION ALL) всех таблиц, входящих в состав критерия. Если в состав критерия входит 50 видов документов, а вам нужен только один, фильтрация через ССЫЛКА в ГДЕ критически важна для производительности. Это позволяет платформе исключить лишние 49 таблиц из процесса поиска.
Также стоит помнить о возможности наличия "битых ссылок" (объектов, удаленных непосредственно из базы данных без контроля ссылочной целостности). Обращение к реквизитам через точку, такое как Ссылка.Проведен, эффективно отсеивает такие ссылки, так как для несуществующего объекта значение реквизита будет равно NULL, и условие в ГДЕ не будет выполнено.
Подведем итог нашему разбору. Для эффективной работы с критериями отбора в 1С:
ССЫЛКА в секции ГДЕ для фильтрации по типу объекта.ВЫРАЗИТЬ для безопасного и быстрого обращения к специфическим реквизитам конкретного типа документа.ВЫБРАТЬ ПЕРВЫЕ 1 и обязательную сортировку УПОРЯДОЧИТЬ ПО.