Как использовать подзапрос в конструкции ВЫБОР КОГДА в 1С:Предприятии?

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

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

Почему нельзя использовать подзапрос внутри ВЫБОР КОГДА?

Язык запросов 1С:Предприятия — это декларативный язык, который транслируется в SQL-запросы к СУБД. Конструкция ВЫБОР КОГДА является выражением, которое должно возвращать конкретное скалярное значение. Вложенный запрос ВЫБРАТЬ ... ИЗ ..., в свою очередь, является самостоятельной выборкой данных. Архитектурно язык запросов 1С не поддерживает размещение целых табличных выражений внутри операторов выбора. В ветках ТОГДА и ИНАЧЕ допускается использовать только поля, параметры или простые вычисления, но не полноценные ВЫБРАТЬ конструкции.

Решение задачи: использование левого соединения

Наиболее эффективным и «правильным» с точки зрения производительности способом получения данных из связанных таблиц или табличных частей является ЛЕВОЕ СОЕДИНЕНИЕ. Давайте разберем по шагам, как это реализовать.

Представим, что у нас есть задача: получить контактное лицо из табличной части документа Событие, если основанием является именно этот документ. Вместо того чтобы пытаться выполнить подзапрос внутри условия, мы сделаем следующее:

  1. Присоединим к основному запросу таблицу участников документа через левое соединение.
  2. Ограничим выборку только первой записью из этой таблицы, чтобы избежать дублирования строк в итоговом результате.
  3. Используем ВЫБОР КОГДА для выбора уже готового поля, полученного через соединение.

Рассмотрим пример реализации такого запроса:


ВЫБРАТЬ
    ЗадачаСотрудника.Ссылка КАК Задача,
    ВЫБОР
        КОГДА ЗадачаСотрудника.Основание ССЫЛКА Справочник.Контрагенты
            ТОГДА ЗадачаСотрудника.Основание
        КОГДА ЗадачаСотрудника.Основание ССЫЛКА Документ.Событие
            ТОГДА СобытиеУчастники.Контакт
        ИНАЧЕ ЗадачаСотрудника.Основание.Контрагент
    КОНЕЦ КАК Результат
ИЗ
    Документ.ЗадачаСотрудника КАК ЗадачаСотрудника
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.Событие.Участники КАК СобытиеУчастники
    ПО ЗадачаСотрудника.Основание = СобытиеУчастники.Ссылка
    И СобытиеУчастники.НомерСтроки = 1

Почему это лучший вариант?

Проанализируем преимущества данного подхода:

Альтернативный подход: Пакет запросов

Если логика получения данных из табличной части документа очень сложная (например, нужно отфильтровать участников по нескольким критериям, а не просто взять первого), рекомендуем использовать пакет запросов. В этом случае работа разбивается на этапы:

  1. Первым пакетом мы выбираем нужные данные из табличной части и помещаем их во ВРЕМЕННУЮ ТАБЛИЦУ.
  2. При создании временной таблицы мы можем сразу наложить любые сложные отборы, использовать ПЕРВЫЕ 1 или ГРУППИРОВАТЬ ПО.
  3. Во втором (основном) пакете мы делаем обычное ЛЕВОЕ СОЕДИНЕНИЕ уже с этой временной таблицей.

Такой подход делает код «чистым», позволяет легко отлаживать каждый этап выборки данных и избавляет от громоздких конструкций внутри одного единственного запроса. Не стоит бояться соединений — при грамотном использовании индексов они являются основой быстродействия платформы 1С:Предприятие. При работе со сложными пакетами для корректного освобождения памяти можно использовать инструмент для оптимизации временных таблиц в пакетных запросах.

← На главную