Что такое таблица-источник данных в запросах 1С и как правильно использовать вложенные запросы

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

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

В этой статье мы подробно разберем, что скрывается под этим понятием, детально проанализируем варианты использования вложенных запросов, рассмотрим особенности работы с ними в интерактивном Конструкторе запросов 1С, а также затронем важнейшие аспекты оптимизации производительности СУБД.

Что такое таблица-источник данных в концепции 1С?

Прежде чем перейти к практике, давайте разберемся с терминологией. В языке запросов 1С (который во многом основан на стандартах SQL) любая выборка данных происходит из какого-либо источника. Источником данных могут выступать:

  1. Реальные (физические) таблицы базы данных — это таблицы, в которых СУБД непосредственно хранит информацию (например, справочники, документы, константы).
  2. Виртуальные таблицы — это таблицы, которые платформа 1С формирует «на лету» на основе физических таблиц (например, срезы последних для регистров сведений или остатки и обороты для регистров накопления).
  3. Временные таблицы — таблицы, созданные разработчиком в рамках текущего сеанса запроса с помощью ключевого слова ПОМЕСТИТЬ.
  4. Вложенные запросы — это конструкции, когда результатом выполнения одного (внутреннего) запроса является динамическая таблица, к которой мы обращаемся из внешнего запроса. Именно эта динамическая таблица и называется таблицей-источником данных.
  5. Внешние таблицы значений — предварительно подготовленные в коде коллекции, которые передаются в запрос в качестве параметра (доступно при использовании временных таблиц).

Таким образом, когда мы пишем конструкцию ВЫБРАТЬ ... ИЗ (...) КАК ИмяИсточника, мы используем вложенный запрос именно в качестве таблицы-источника.

Детальный разбор вопроса 07.06 экзамена «1С:Профессионал»

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

Формулировка вопроса: «Вложенный запрос может использоваться...»

Вариант 1: В качестве таблицы-источника данных

В данном сценарии вложенный запрос выступает полноценной «виртуальной» таблицей в секции ИЗ основного запроса. Для СУБД эта конструкция выглядит как подзапрос (subquery). Главное правило синтаксиса 1С в данном случае — вложенному запросу обязательно должен быть присвоен уникальный псевдоним (имя источника), к которому мы сможем обращаться во внешнем запросе.

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


ВЫБРАТЬ
    ВложенныйИсточник.Номенклатура КАК Номенклатура,
    ВложенныйИсточник.СуммаОборот КАК СуммаОборот
ИЗ
    (ВЫБРАТЬ
        ПродажиОбороты.Номенклатура КАК Номенклатура,
        ПродажиОбороты.СуммаОборот КАК СуммаОборот
     ИЗ
        РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты) КАК ВложенныйИсточник

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

Вариант 2: В качестве операнда операций сравнения «В» или «НЕ В» при задании параметров виртуальной таблицы

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

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


ВЫБРАТЬ
    ТоварыОстатки.Номенклатура,
    ТоварыОстатки.Склад,
    ТоварыОстатки.ВНаличииОстаток
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(
        &Период,
        Номенклатура В (ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ Услуга = ЛОЖЬ)
    ) КАК ТоварыОстатки

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

Вариант 3: В качестве операнда операций сравнения «В» или «НЕ В» при задании конструкции «ГДЕ»

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

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


ВЫБРАТЬ
    Реализация.Ссылка,
    Реализация.Дата,
    Реализация.Контрагент
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Контрагент В (ВЫБРАТЬ Ссылка ИЗ Справочник.Контрагенты ГДЕ ЮрЛицо = ИСТИНА)

Поскольку все три варианта использования вложенного запроса синтаксически верны и активно применяются в платформе, правильным ответом в тестировании является интегральный вариант: «Верны ответы 1, 2 и 3».

Как работать с вложенными запросами в Конструкторе запросов 1С

Давайте разберем по шагам, как визуально выглядит создание вложенного запроса в стандартном Конструкторе запросов в режиме Конфигуратора. Это поможет лучше сопоставить сухой текст теории с реальным интерфейсом платформы.

  1. Откроем Конструктор запросов.
  2. Обратим внимание на вкладку «Таблицы и поля». Экран разделен на три основные колонки:
    • Левая колонка («База данных»): Отображает дерево доступных объектов конфигурации (справочники, документы, регистры).
    • Средняя колонка («Таблицы»): Сюда мы перетаскиваем те таблицы, из которых планируем выбирать данные. Это и есть наши источники.
    • Правая колонка («Поля»): Здесь отображаются конкретные реквизиты и поля, которые мы хотим видеть в результате выполнения запроса.
  3. Чтобы использовать вложенный запрос в качестве источника данных, найдем в средней колонке («Таблицы») командную панель сверху. Первая пиктограмма на этой панели называется «Создать вложенный запрос».
  4. При нажатии на эту кнопку откроется новое, вложенное окно конструктора. Мы можем работать с ним точно так же, как и с основным: выбирать таблицы базы данных, настраивать условия и группировки.
  5. После нажатия кнопки «ОК» во вложенном окне, в нашей средней колонке основного конструктора появится новая таблица с характерным значком. Мы можем переименовать её (задать псевдоним источника) и выбирать из неё поля в правую колонку.

Важное примечание разработчику: Если вы работаете в режиме управляемого приложения непосредственно в режиме «1С:Предприятие» (например, редактируете схему компоновки данных в отчете пользователя), интерактивный конструктор может иметь ограничения. В таких случаях вложенные конструкции в условиях связи или сложных выражениях зачастую приходится дописывать вручную с клавиатуры.

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

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

Выясним причину такого подхода и проанализируем различия.

Проблема оценки кардинальности СУБД (Антипаттерн)

Когда мы соединяем физическую таблицу с вложенным запросом (например, используя ЛЕВОЕ СОЕДИНЕНИЕ), современные СУБД (MS SQL Server, PostgreSQL, IBM DB2) не всегда способны корректно оценить, сколько именно строк вернет этот вложенный запрос. Это называется проблемой оценки кардинальности (Cardinality Estimation).

Не имея точной статистики по объему данных внутри вложенного запроса, оптимизатор СУБД может построить крайне неэффективный план запроса — например, использовать медленный алгоритм Nested Loops (вложенные циклы) вместо быстрого Hash Match (соединение хешированием). На больших базах данных это приводит к драматическому падению производительности, блокировкам таблиц и зависанию системы.

Решение: Использование временных таблиц

Вместо вложенного запроса рекомендуется использовать пакетные запросы с помещением промежуточных результатов во временные таблицы с помощью конструкции ПОМЕСТИТЬ.

Рассмотрим, как можно переписать неоптимальный вложенный запрос в производительный пакетный вариант.

Плохо (использование вложенного запроса в соединении):


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

Хорошо (перенос данных во временную таблицу):


ВЫБРАТЬ
    Обороты.Номенклатура КАК Номенклатура,
    СУММА(Обороты.СуммаОборот) КАК СуммаОборот
ПОМЕСТИТЬ Вт_Продажи
ИЗ
    РегистрНакопления.Продажи.Обороты КАК Обороты
ГРУППИРОВАТЬ ПО
    Обороты.Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Товары.Ссылка КАК Товар,
    ЕСТЬNULL(Продажи.СуммаОборот, 0) КАК Сумма
ИЗ
    Справочник.Номенклатура КАК Товары
    ЛЕВОЕ СОЕДИНЕНИЕ Вт_Продажи КАК Продажи
    ПО Товары.Ссылка = Продажи.Номенклатура

Разберем по шагам преимущества второго варианта:

  1. Предсказуемость для СУБД: На этапе соединения со второй таблицей СУБД точно знает количество записей во временной таблице Вт_Продажи, так как она уже физически создана и заполнена в базе данных tempdb. Оптимизатор строит идеальный план выполнения.
  2. Возможность индексации: Если объем данных во временной таблице велик (более нескольких сотен строк), мы можем применить ключевое слово ИНДЕКСИРОВАТЬ ПО. Индексирование по полю связи (в нашем случае по Номенклатура) ускоряет операцию соединения в разы.
  3. Читаемость и отладка кода: Пакетный запрос, разделенный символом точки с запятой (;), читать и анализировать в консоли запросов гораздо проще, чем огромные вложенные конструкции «вложенный запрос во вложенном запросе».

Когда использование вложенных запросов все же оправдано?

Не стоит полностью отказываться от вложенных запросов. Они вполне применимы и полезны в следующих сценариях:

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

← На главную