К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как выбрать данные из запроса 1С

Как правильно выбрать данные из запроса 1С: конструкция ВЫБРАТЬ, обход выборки, условия, соединения, типовые ошибки и проверка результата на практике.

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

Ошибки на этом этапе приводят к типичным проблемам: запрос возвращает пустой результат, хотя данные есть; выборка обходится медленно на больших таблицах; в отчёт попадают лишние строки из-за неправильного соединения. Всё это решается корректным построением текста запроса и правильной обработкой результата.

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

Как устроена конструкция ВЫБРАТЬ в языке запросов 1С

Минимальный запрос состоит из ключевого слова ВЫБРАТЬ, списка полей и предложения ИЗ с именем таблицы. Например, выбор всех элементов справочника номенклатуры:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

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

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

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

|ИЗ

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

Обратите внимание на псевдоним таблицы (КАК Номенклатура): он упрощает чтение запроса и обязателен при соединении нескольких таблиц. Вместо перечисления полей допустимо указать *, но в рабочем коде этого лучше избегать — выбираются все поля, включая ненужные, что увеличивает нагрузку на сервер и объём передаваемых данных.

Поле Ссылка — уникальный идентификатор объекта. Через него удобно получать сам объект методом ПолучитьОбъект(), если нужно не только прочитать, но и изменить данные. Для чтения достаточно реквизитов, перечисленных в запросе, — обращение к объекту целиком замедляет выборку.

Как получить результат: Выбрать() или Выгрузить()

После выполнения запроса методом Запрос.Выполнить() результат обрабатывают двумя способами. Первый — выборка с обходом в цикле:

Результат = Запрос.Выполнить();

Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

Сообщить(Выборка.Наименование + " — " + Выборка.Артикул);

КонецЦикла;

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

ТаблицаРезультат = Запрос.Выполнить().Выгрузить();

Таблица значений удобна, когда данные нужно сортировать, сворачивать, искать строки методом Найти() или привязывать к элементу формы. Минус — весь результат целиком загружается в память, что при сотнях тысяч строк может привести к замедлению или ошибке нехватки памяти.

Выбрать() или Выгрузить()

Выбрать() с циклом

Подходит для построчной обработки больших объёмов и записи данных; не даёт произвольного доступа к строкам

Выгрузить() в таблицу значений

Подходит для поиска, сортировки и отображения на форме; ограничен объёмом памяти при больших результатах

Как задать условия отбора через ГДЕ и параметры

Отбор строк выполняется предложением ГДЕ. Условия никогда не вставляют в текст запроса конкатенацией строк — только через параметры. Это защищает от ошибок с типами данных и делает запрос безопасным:

Запрос.Текст =

"ВЫБРАТЬ

| Реализация.Ссылка,

| Реализация.Дата,

| Реализация.СуммаДокумента

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ

| Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода

| И Реализация.Контрагент = &Контрагент";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("Контрагент", ВыбранныйКонтрагент);

Для отбора по списку значений используют оператор В с предварительно заполненным массивом или списком значений. Для поиска по части строки — оператор ПОДОБНО с символом процента: Наименование ПОДОБНО &Маска, где в параметр передают, например, "%кабель%".

Частая ситуация — пустой результат при корректном на вид запросе. Причины: несовпадение типа параметра с типом поля (например, передана строка вместо ссылки), границы периода заданы без учёта времени, либо в условии участвует поле, которое в данных содержит NULL.

Как работать с виртуальными таблицами регистров

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

Запрос.Текст =

"ВЫБРАТЬ

| Остатки.Номенклатура,

| Остатки.КоличествоОстаток

|ИЗ

| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОстатков, Склад = &Склад) КАК Остатки";

Важное правило: условия по измерениям регистра задавайте в параметрах виртуальной таблицы, а не в предложении ГДЕ. Отбор в параметрах выполняется до формирования виртуальной таблицы и работает значительно быстрее, чем фильтрация уже построенного результата.

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

Как соединять таблицы и избегать дублирования строк

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

Запрос.Текст =

"ВЫБРАТЬ

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

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

| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК Остаток

|ИЗ

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

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

| ПО Номенклатура.Ссылка = Остатки.Номенклатура";

При левом соединении поля правой таблицы для несовпавших строк содержат NULL, поэтому функция ЕСТЬNULL обязательна, если значение участвует в расчётах или выводится пользователю. Соединение по нескольким условиям перечисляют через И в части ПО.

Дублирование строк — главный признак ошибки соединения: если в правой таблице несколько строк соответствуют одной строке левой (например, остатки по нескольким складам), каждая комбинация даст отдельную строку результата. Решение — предварительно сгруппировать правую таблицу во временной таблице или явно учитывать детализацию в итоговом запросе.

Типичные ошибки
01
Левое соединение с таблицей, где несколько строк на ключ — результат размножается, суммы в отчёте завышаются
02
Условие на поле правой таблицы в ГДЕ при левом соединении — соединение фактически превращается во внутреннее, строки теряются
03
Конкатенация значений в текст запроса вместо параметров — ошибки типов и риск некорректной выборки
04
Выбор всех полей через * и обращение к объекту через ПолучитьОбъект() в цикле — резкое падение производительности
05
Игнорирование NULL при соединениях — ошибки сравнения и пустые значения в расчётах

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

Первый шаг проверки — консоль запросов: инструмент, позволяющий выполнить текст запроса с реальными параметрами и увидеть результат до встраивания в код. В управляемых формах используют типовые или внешние консоли запросов; в конфигураторе текст удобно собирать конструктором запроса через контекстное меню.

Проверяйте три вещи: количество строк (соответствует ли ожиданиям на контрольном примере), наличие NULL в ключевых полях и корректность сумм — сверьте итог по запросу с типовым отчётом конфигурации за тот же период. Расхождение сумм почти всегда означает проблему с соединениями или отборами.

Перед обходом выборки полезно проверить, не пуст ли результат: метод Результат.Пустой() возвращает Истина, если строк нет. Это позволяет корректно обработать ситуацию без лишнего цикла и выдать пользователю понятное сообщение.

Контрольные точки

Как проверить результат

Количество строк выборки
Норма

Совпадает с числом записей при ручном подсчёте в списке

Тревожный признак

Строк больше — вероятно дублирование при соединении

Итоговые суммы
Норма

Сходятся с типовым отчётом за тот же период

Тревожный признак

Расхождение — проверить отборы и виртуальные таблицы

Значения ключевых полей
Норма

Заполнены для всех строк

Тревожный признак

NULL там, где ожидается значение — проблема соединения или ЕСТЬNULL

Когда запрос не подходит: альтернативные способы получения данных

Запрос — не единственный инструмент. Для чтения одного объекта по известной ссылке достаточно обращения к реквизитам через точку — платформа сама выполнит обращение к базе, и отдельный запрос не нужен. Для получения предопределённых элементов справочника используют обращение через менеджер: Справочники.Валюты.НайтиПоКоду("643").

Для отчётов с настройками пользователя вместо программного запроса применяют СКД (систему компоновки данных): она использует тот же язык запросов, но добавляет отборы, группировки и оформление без изменения кода. Для обмена данными между базами запрос часто заменяют планами обмена или сервисами.

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

Маршрут решения

Как выбрать действие

Нужны множество записей по условию для программной обработкиИспользуйте запрос с ВЫБРАТЬ и параметрами
Нужен один объект по известной ссылкеОбратитесь к реквизитам через ссылку без запроса
Пользователь должен сам настраивать отборы и группировкиИспользуйте СКД вместо программного запроса
Нужны остатки или обороты за периодИспользуйте виртуальные таблицы регистров с параметрами

Частые вопросы

Запрос возвращает пустой результат, хотя данные в базе есть. Что проверить?

Сначала выполните запрос в консоли с теми же параметрами. Чаще всего причина в несовпадении типа параметра (строка вместо ссылки), неверных границах периода с учётом времени или в том, что условие накладывается на поле со значением NULL. Проверьте также, не отсекают ли строки условия соединения.

Чем отличается Результат.Выбрать() от Результат.Выгрузить()?

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

Как выбрать только первые несколько записей?

Используйте конструкцию ВЫБРАТЬ ПЕРВЫЕ N, где N — число строк, в сочетании с УПОРЯДОЧИТЬ ПО. Без упорядочивания «первые» записи не имеют определённого смысла, и набор может отличаться от ожидаемого.

Почему при левом соединении пропадают строки левой таблицы?

Почти всегда причина в условии ГДЕ по полю правой таблицы: для несовпавших строк это поле равно NULL, условие не выполняется, и строка отбрасывается. Перенесите условие в часть ПО соединения или обработайте NULL через ЕСТЬNULL.

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

Нет, язык запросов 1С только читает данные. Для изменения получают объект через ссылку методом ПолучитьОбъект(), изменяют реквизиты и вызывают Записать(). Запрос при этом используют только для поиска нужных ссылок.

Как передать в запрос список значений для отбора?

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

Итог

Что важно запомнить

Выбор данных в 1С строится на конструкции ВЫБРАТЬ с параметризованными условиями ГДЕ, результат обходят через Выбрать() или выгружают в таблицу значений. Остатки и обороты берут из виртуальных таблиц с параметрами, соединения сопровождают обработкой NULL, а корректность результата сверяют с типовыми отчётами.