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

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

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

Базовая структура и синтаксис запроса

Любой запрос в 1С строится по определенной логической схеме, которая определяет, какие данные будут выбраны и как они будут отфильтрованы. Основным оператором здесь выступает ВЫБРАТЬ, который указывает системе, какие поля необходимо получить в результат. В отличие от чистого SQL, в 1С важно понимать разницу между физическими таблицами и объектами метаданных, к которым мы обращаемся.

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

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

💡

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

Рассмотрим простейший пример получения списка номенклатуры:

ВЫБРАТЬ

Номенклатура.Ссылка КАК Ссылка,

Номенклатура.Наименование КАК Наименование

ИЗ

Справочник.Номенклатура КАК Номенклатура

ГДЕ

Номенклатура.ЭтоГруппа = ЛОЖЬ

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

Работа с параметрами и условиями отбора

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

Синтаксически параметры обозначаются знаком амперсанда & перед именем. Например, &ДатаНачала или &Контрагент. Перед выполнением запроса программист обязан заполнить значения этих параметров через объект Запрос.УстановитьПараметр. Если этого не сделать, система выдаст ошибку о том, что параметр не определен.

Особенность работы с параметрами типа Дата

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

Часто возникает необходимость в проверке на заполненность. В таких случаях используется конструкция ЕСТЬ NULL. Это позволяет писать гибкие условия, когда фильтр применяется только в том случае, если пользователь действительно ввел значение в форму отчета.

  • 📅 Периоды: Использование параметров даты для срезов регистров.
  • 🏢 Организации: Фильтрация по конкретному юридическому лицу в многопользовательской базе.
  • 📦 Статусы: Отбор документов только с определенным статусом проведения.

Пример запроса с параметрами выглядит следующим образом:

ВЫБРАТЬ

Продажи.Период,

Продажи.Сумма

ИЗ

РегистрНакопления.Продажи.Обороты(

&ДатаНачала,

&ДатаКонца,

,

Номенклатура = &Номенклатура

) КАК Продажи

Здесь мы видим использование виртуальной таблицы оборотов, которая автоматически рассчитывает итоги за указанный период. Параметры &ДатаНачала и &ДатаКонца определяют границы этого периода.

Соединение таблиц и типы JOIN

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

Самым распространенным является ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN). Оно возвращает все записи из левой таблицы (указанной после ИЗ) и соответствующие им записи из правой таблицы. Если соответствия нет, поля правой таблицы будут заполнены NULL. Это идеально подходит для ситуаций, когда нужно показать все товары, даже те, которые еще не продавались.

⚠️ Внимание: Использование ВНУТРЕННЕГО СОЕДИНЕНИЯ (INNER JOIN) отбрасывает все записи, у которых нет пары в соединяемой таблице. Если вы используете его для соединения с регистром сведений, вы можете потерять документы, для которых еще не заполнены некоторые дополнительные реквизиты.

Также существуют ПРАВОЕ СОЕДИНЕНИЕ и ПОЛНОЕ СОЕДИНЕНИЕ, однако они используются значительно реже и часто могут быть заменены изменением порядка таблиц или использованием левых соединений для лучшей читаемости кода.

📊 Какой тип соединения вы используете чаще всего?
ЛЕВОЕ СОЕДИНЕНИЕ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
ПОЛНОЕ СОЕДИНЕНИЕ
ПРАВОЕ СОЕДИНЕНИЕ

Пример левого соединения для получения наименований товаров к продажам:

ВЫБРАТЬ

Продажи.Номенклатура,

Номенклатура.Наименование

ИЗ

РегистрНакопления.Продажи.Обороты КАК Продажи

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

ПО Продажи.Номенклатура = Номенклатура.Ссылка

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

Группировка и агрегатные функции

Когда перед разработчиком стоит задача построить отчет с итогами, простого выбора полей недостаточно. Необходимо объединять строки по определенным признакам и вычислять суммы, количества или средние значения. Для этого в запросе используется оператор СГРУППИРОВАТЬ ПО.

Все поля, которые не участвуют в агрегатных функциях (таких как СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ), должны быть обязательно перечислены в блоке группировки. Если вы попытаетесь выбрать поле, не входящее в группировку и не обернутое в функцию, сервер 1С выдаст ошибку синтаксиса.

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

💡

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

Рассмотрим таблицу с примерами часто используемых агрегатных функций:

Функция Описание Пример использования
СУММА(Поле) Вычисляет общую сумму значений СУММА(Продажи.Сумма)
КОЛИЧЕСТВО(Поле) Подсчитывает количество записей КОЛИЧЕСТВО(Продажи.ДокументПродажи)
МИНИМУМ(Поле) Находит наименьшее значение МИНИМУМ(Продажи.Дата)
ЕСТЬ(Поле) Проверяет наличие не NULL значений ЕСТЬ(Контрагенты.ИНН)

Важно отметить, что функция ЕСТЬ возвращает булево значение (ИСТИНА/ЛОЖЬ) и часто используется для проверки заполнения реквизитов в сгруппированных данных. Это позволяет отфильтровать группы, где определенные данные отсутствуют.

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

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

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

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

  • Производительность: Данные хранятся в памяти, доступ к ним быстрее, чем к диску.
  • 🔄 Модульность: Сложный запрос разбивается на логические этапы.
  • 🗑️ Автоматическая очистка: Таблица удаляется после завершения сеанса или выполнения соединения.

Пример создания и использования временной таблицы:

ПОМЕСТИТЬ ВТ_Продажи

ВЫБРАТЬ

Продажи.Номенклатура,

СУММА(Продажи.Количество) КАК Количество

ИЗ

РегистрНакопления.Продажи.Обороты КАК Продажи

СГРУППИРОВАТЬ ПО

Продажи.Номенклатура

;

ВЫБРАТЬ

ВТ_Продажи.Номенклатура,

ВТ_Продажи.Количество,

Номенклатура.Наименование

ИЗ

ВТ_Продажи КАК ВТ_Продажи

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

ПО ВТ_Продажи.Номенклатура = Номенклатура.Ссылка

Разделитель ; (точка с запятой) обязателен между запросом, создающим временную таблицу, и последующими запросами. Без него система не поймет, где заканчивается один блок инструкций и начинается другой.

Типичные ошибки и оптимизация

Даже опытные разработчики могут допускать ошибки при написании запросов, которые приводят к тормозам системы в момент пиковой нагрузки. Одной из самых частых проблем является выборка лишних полей. Не нужно выбирать * или все поля таблицы, если для работы отчета требуются только два из них. Лишние данные увеличивают трафик между сервером и клиентом.

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

⚠️ Внимание: Избегайте использования функций в левой части условия сравнения в блоке ГДЕ. Например, конструкция ГДЕ ГОД(Дата) = 2026 заставит базу данных перебирать все записи, так как индекс по полю Дата не сможет быть использован. Лучше писать диапазон дат: ГДЕ Дата >= '2026.01.01' И Дата < '2026.01.01'.

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

☑️ Проверка запроса перед запуском

Выполнено: 0 / 5

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

Как debugировать запрос, который выдает пустой результат?

Если запрос не возвращает данных, сначала проверьте типы данных параметров. Частая ошибка — передача Строки вместо Числа или Даты. Затем упростите запрос, убрав все условия ГДЕ и соединения, чтобы убедиться, что данные в таблице вообще есть. Постепенно возвращайте условия, проверяя результат после каждого шага.

Можно ли выполнять вставку или обновление данных через запрос?

Нет, язык запросов 1С предназначен только для чтения данных (SELECT). Для изменения данных (INSERT, UPDATE, DELETE) необходимо использовать объекты доступа к данным (Документы, Регистры) или специальные методы объекта Запрос, такие как ВыполнитьПакет с DDL-операциями, но это требует повышенных привилегий и осторожности.

В чем разница между Виртуальными таблицами и обычными?

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