Как сделать динамическое соединение с таблицей в запросе 1С, если данные в ней могут отсутствовать?

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

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

Решение с использованием конструкции ВЫБОР-КОГДА в секции ГДЕ

Один из самых гибких способов решения — использование логической конструкции ВЫБОР непосредственно в секции ГДЕ. Этот подход позволяет нам проверять наличие записей в таблице втОборудование и в зависимости от результата применять фильтр или снимать его.

Разберем этот метод по шагам:

  1. Сначала мы проверяем, содержит ли наша временная таблица хотя бы одну запись с помощью подзапроса.
  2. Если записи есть, мы ограничиваем выборку только теми записями, которые содержатся в правой таблице.
  3. Если записей нет, мы возвращаем ИСТИНА, что фактически отменяет фильтрацию и позволяет вывести все данные.

Посмотрим, как это выглядит в коде:


ГДЕ 
    ВЫБОР
        КОГДА ИСТИНА В
            (ВЫБРАТЬ ПЕРВЫЕ 1 ИСТИНА ИЗ втОборудование КАК втОборудование)
        ТОГДА МестаРаботыСпециалистов.МестоРаботы В
            (ВЫБРАТЬ втОборудование.Оборудование ИЗ втОборудование КАК втОборудование)
        ИНАЧЕ ИСТИНА
    КОНЕЦ

Этот способ удобен тем, что он не требует изменения структуры соединения (мы продолжаем использовать ВНУТРЕННЕЕ СОЕДИНЕНИЕ или ЛЕВОЕ СОЕДИНЕНИЕ в зависимости от нужд), а вся логика управления данными концентрируется в одном блоке условий.

Решение через объединение запросов (ОБЪЕДИНИТЬ)

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

Давайте проанализируем структуру такого решения:

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


// Часть 1: Случай, когда оборудование не выбрано
ВЫБРАТЬ ...
ИЗ Таб1
ГДЕ НЕ ИСТИНА В (ВЫБРАТЬ ПЕРВЫЕ 1 ИСТИНА ИЗ Таб2)

ОБЪЕДИНИТЬ ВСЕ

// Часть 2: Случай, когда фильтр по оборудованию обязателен
ВЫБРАТЬ ...
ИЗ Таб1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Таб2 ПО ...

Важные рекомендации по производительности

При работе с такими конструкциями важно учитывать несколько архитектурных моментов, чтобы запрос не замедлял систему:

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

← На главную