Почему запрос с использованием вложенного условия возвращает пустую таблицу в 1С?

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

При разработке отчетов в 1С:Предприятии начинающие разработчики часто сталкиваются с непониманием того, как работают механизмы вложенных запросов. Ситуация, когда запрос, который кажется логически верным с точки зрения классического SQL, возвращает пустой результат, встречается довольно часто. Давайте разберем, в чем заключается причина такого поведения и как правильно решать подобные аналитические задачи в среде 1С.

Разбор проблемы: корреляция в 1С

Проблема автора заключается в попытке использовать вложенный запрос как полноценный коррелированный подзапрос. В классических СУБД, таких как MS SQL Server, коррелированный подзапрос может обращаться к полям внешней таблицы на каждой итерации. В платформе 1С:Предприятие механизм корреляции ограничен конструкцией В (...).

Когда вы пишете запрос вида:


ВЫБРАТЬ
    Т1.Ссылка
ИЗ
    Документ.ОтчетПоПродажам.Продажи КАК Т1
ГДЕ
    Т1.Ссылка В (
        ВЫБРАТЬ
            Т2.Ссылка
        ИЗ
            Документ.ОтчетПоПродажам.Продажи КАК Т2
        ГДЕ
            Т1.Номенклатура = Т2.Номенклатура
            И Т1.ДатаПродажи < Т2.ДатаПродажи
    )

Платформа не выполняет «цикл» в обычном понимании. Она ожидает, что вложенный запрос вернет набор данных, который будет использоваться как фильтр. Если условие Т1.ДатаПродажи < Т2.ДатаПродажи не выполняется ни для одной пары записей, вложенный запрос возвращает пустоту, а внешний запрос — закономерно пустой результат.

Почему это не работает так, как вы ожидаете

Основная причина — отсутствие поддержки полноценных коррелированных подзапросов в списке выбора или полноценных условиях JOIN вложенных запросов в 1С. В 1С вложенный запрос в условии ГДЕ ... В (...) работает как проверка на вхождение. Если для конкретной строки документа не нашлось ни одной записи, удовлетворяющей условию Т1.ДатаПродажи < Т2.ДатаПродажи, то для этой строки вернется ЛОЖЬ, и она будет исключена из выборки.

Как правильно реализовывать такие задачи

Для сравнения записей внутри одного набора данных в 1С существует два основных «золотых» стандарта разработки:

1. Использование соединения таблицы с самой собой (Self-Join)

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


ВЫБРАТЬ
    Т1.Ссылка КАК Ссылка,
    Т1.Номенклатура КАК Номенклатура,
    Т1.ДатаПродажи КАК ДатаПродажи
ИЗ
    Документ.ОтчетПоПродажам.Продажи КАК Т1
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ОтчетПоПродажам.Продажи КАК Т2
    ПО Т1.Номенклатура = Т2.Номенклатура
    И Т1.ДатаПродажи < Т2.ДатаПродажи

Такой подход позволяет платформе 1С оптимизировать план выполнения запроса, используя индексы по полям соединения (в данном случае по Номенклатура и ДатаПродажи).

2. Использование временных таблиц

Если задача требует сложной предварительной обработки (например, сначала нужно сгруппировать данные, а потом сравнить их с исходными), используйте пакетные запросы с ПОМЕСТИТЬ.

Шаги реализации:

  1. Создайте временную таблицу с рассчитанными показателями.
  2. Проиндексируйте временную таблицу по нужным полям (например, по Номенклатура).
  3. Выполните основное соединение с этой временной таблицей.

ВЫБРАТЬ
    Продажи.Номенклатура КАК Номенклатура,
    МАКСИМУМ(Продажи.ДатаПродажи) КАК МаксДата
ПОМЕСТИТЬ ВремТаблица
ИЗ
    Документ.ОтчетПоПродажам.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
    Продажи.Номенклатура
;
ИНДЕКСИРОВАТЬ ПО
    ВремТаблица.Номенклатура
;
ВЫБРАТЬ
    *
ИЗ
    Документ.ОтчетПоПродажам.Продажи КАК Продажи
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВремТаблица КАК Врем
    ПО Продажи.Номенклатура = Врем.Номенклатура

Советы по отладке запросов

Если вы не уверены, почему запрос не возвращает данные:

Использование Self-Join является предпочтительным способом решения задач, связанных с сравнением текущей записи с предыдущими или следующими в 1С:Предприятии. Это делает код читаемым, производительным и предсказуемым для платформы.

← На главную