Работа с данными в платформе 1С:Предприятие невозможна без понимания того, как извлекать информацию из документов. Самая частая задача для разработчика — это необходимость получить список товаров, услуг или материалов, которые находятся внутри конкретного документа. Именно для этого и нужен правильный запрос к табличной части. Новички часто путаются в синтаксисе или пытаются перебирать строки циклом, что убивает производительность системы.
В этой статье мы разберем механизм формирования запроса к вложенным данным максимально подробно. Вы узнаете, как обращаться к полям, как связывать заголовок документа со строками и как избегать типичных ошибок, приводящих к дублированию записей. Понимание этой темы критически важно для написания эффективного кода на языке запросов 1С.
Запрос к табличной части отличается от запроса к регистру или справочнику только способом указания пути к данным. Если вы умеете работать с обычными таблицами, то освоение работы с вложенными структурами займет у вас совсем немного времени. Главное — соблюдать строгий синтаксис платформы и понимать логику соединения таблиц.
Синтаксис обращения к вложенным таблицам
Основное правило работы с документами в языке запросов — это использование точки для разделения имен полей. Когда вы пишете запрос, система должна точно понимать, к какой именно структуре вы обращаетесь. Табличная часть является свойством документа, поэтому путь к ней строится иерархически. Вы указываете имя таблицы запроса, затем точку и имя самой табличной части.
Например, если у вас есть документ РеализацияТоваровУслуг, то его товарная часть обычно называется Товары. Чтобы выбрать все строки из этого документа, вам нужно указать путь Реализация.Товары.
Рассмотрим базовую структуру такого запроса. В секции ИЗ мы указываем источник данных. Если нам нужны только строки документа, мы пишем имя документа, точку и имя раздела. При этом в списке выбора мы также должны использовать этот префикс, чтобы указать, какие именно поля строки нам интересны. Это позволяет избежать конфликта имен, если в заголовке и в строке есть поля с одинаковыми названиями, например, Комментарий.
⚠️ Внимание: Никогда не пытайтесь выбрать поле табличной части без указания пути к ней в списке выбора. Платформа просто не поймет, откуда брать данные, и выдаст ошибку синтаксиса или логическую ошибку выполнения.
Часто разработчики забывают, что обращение к табличной части без указания конкретного документа в условиях отбора приведет к выборке строк из всех документов этого вида в базе данных. Это может быть полезно для отчетов, но опасно для обработки одного конкретного объекта. Всегда проверяйте, ограничиваете ли вы выборку нужным документом.
Структура запроса с использованием ССЫЛКА
Для того чтобы связать строки табличной части с конкретным документом, необходимо использовать поле Ссылка. Это уникальный идентификатор документа в базе данных. В условии ГДЕ мы сравниваем поле ссылки у строки табличной части с параметром или конкретной ссылкой. Синтаксически это выглядит как сравнение двух полей, одно из которых находится "ниже" по иерархии.
Давайте посмотрим на пример кода, который выбирает товары из конкретной реализации. Здесь мы используем параметр &Док, в который передадим ссылку на документ. Такой подход делает запрос универсальным и позволяет выполнять его многократно для разных объектов без перекомпиляции модуля.
ВЫБРАТЬ
РеализацияТоваровУслугТовары.Номенклатура,
РеализацияТоваровУслугТовары.Количество,
РеализацияТоваровУслугТовары.Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
ГДЕ
РеализацияТоваровУслугТовары.Ссылка = &Док
Обратите внимание на алиас таблицы РеализацияТоваровУслугТовары. Использование псевдонимов упрощает чтение кода, особенно когда имена таблиц длинные. В списке выбора и в условиях мы обращаемся именно к этому псевдониму. Это стандарт хорошей практики программирования в 1С, который экономит время на отладку.
Если вам нужно получить не только строки, но и некоторые реквизиты из шапки документа (например, дату или контрагента), вам придется использовать соединение таблиц. Простого обращения к табличной части здесь будет недостаточно, так как данные находятся в разных физических или логических таблицах базы данных.
Используйте параметризированные запросы с символом амперсанда (&) для передачи ссылок на документы. Это защищает от SQL-инъекций и позволяет кэшировать план выполнения запроса сервером 1С.
Соединение шапки документа и табличной части
Самая распространенная ситуация в отчетности — это необходимость вывести список товаров вместе с данными о клиенте и дате отгрузки. Для этого применяется оператор ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN). Мы соединяем таблицу шапки документа с таблицей его строк по полю Ссылка. Это позволяет получить плоскую выборку, где в каждой строке результата будут и данные товара, и данные документа.
При построении такого запроса важно правильно указать условие соединения. Оно всегда строится на равенстве ссылок: ссылка строки должна быть равна ссылке шапки. Если вы забудете это условие или укажете его неверно, получите декартово произведение, что приведет к огромному количеству дублей и зависанию системы.
| Поле в результате | Источник (Таблица) | Описание данных |
|---|---|---|
| Контрагент | Документ.Реализация (Шапка) | Покупатель из заголовка |
| Дата | Документ.Реализация (Шапка) | Дата проведения документа |
| Номенклатура | Документ.Реализация.Товары | Наименование товара из строки |
| Количество | Документ.Реализация.Товары | Число единиц в строке |
В приведенной таблице видно четкое разделение: общие данные берутся из верхнего уровня, а специфические — из вложенного. При написании запроса вы явно указываете, из какой части брать каждое поле. Это дает гибкость в формировании отчетов любой сложности.
Использование ЛЕВОЕ СОЕДИНЕНИЕ гарантирует, что даже если в документе по какой-то причине не окажется строк (что редкость, но возможно), сам документ все равно попадет в выборку. Поля табличной части в таком случае будут заполнены пустыми значениями. Это важно для сверки итогов и поиска "пустых" документов.
☑️ Правильное соединение таблиц
Отбор данных внутри строк документа
Часто требуется выбрать не все товары из документа, а только те, которые соответствуют определенным критериям. Например, нас интересуют только услуги или товары с определенной номенклатурной группой. Фильтрация производится в секции ГДЕ запроса. Условия применяются непосредственно к полям табличной части.
Вы можете комбинировать условия отбора по шапке и по строкам. Это позволяет создавать очень точные выборки. Например: "Найти все документы за сегодня, в которых есть товар с артикулом 12345". В этом случае одно условие будет проверять дату в шапке, а второе — артикул в строке.
При отборе по нескольким строкам одного документа помните о логике работы SQL. Если в документе 10 строк, и 2 из них подходят под условие, то в результат запроса попадут только эти 2 строки. Остальные строки этого же документа отображены не будут, если они не удовлетворяют условию. Это поведение отличается от отбора по самому документу.
⚠️ Внимание: Будьте осторожны при использовании условий ИЛИ (OR) между полями шапки и строками. Логика такого отбора может привести к неожиданным результатам, когда документ попадает в выборку из-за одной строки, но данные другой строки искажают общую картину.
Для оптимизации производительности старайтесь накладывать максимально жесткие условия отбора именно на те поля, по которым в базе данных построены индексы. Обычно это ссылки на справочники (Номенклатура, Контрагенты) и даты. Избегайте отбора по текстовым полям типа Комментарий, если это возможно.
Почему отбор по строкам быстрее?
Отбор по строкам позволяет СУБД использовать индексы конкретных таблиц данных. Если вы сначала выберете все документы, а потом в коде 1С будете фильтровать строки, вы загрузите в память лишние данные, что замедлит работу при больших объемах.
Агрегатные функции и группировка
Запросы к табличным частям часто используются для подсчета итогов: общего количества товаров, суммы документа или среднего веса груза. Для этого применяются агрегатные функции: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ. При их использовании обязательно требуется оператор СГРУППИРОВАТЬ ПО.
Если вы используете агрегатные функции, все поля, которые не участвуют в расчетах, должны быть перечислены в секции группировки. Это строгое требование языка запросов. Например, если вы считаете сумму по каждому товару, то в группировку должен попасть реквизит Номенклатура.
Рассмотрим пример подсчета общего количества проданных единиц по каждому товару за период. Здесь мы группируем данные по номенклатуре, игнорируя разбивку по конкретным документам. Это позволяет свернуть тысячи строк табличных частей в компактный отчет.
ВЫБРАТЬ
Товары.Номенклатура,
СУММА(Товары.Количество) КАК ОбщееКоличество
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ
Товары.Период МЕЖДУ &НачПериода И &КонПериода
СГРУППИРОВАТЬ ПО
Товары.Номенклатура
Использование агрегации на уровне запроса гораздо эффективнее, чем перебор строк в цикле на стороне клиента 1С. Сервер базы данных оптимизирован для таких вычислений и справляется с ними мгновенно, даже если речь идет о миллионах записей. Перекладывайте вычисления на сторону СУБД whenever possible.
Всегда используйте СГРУППИРОВАТЬ ПО для всех неагрегированных полей. Отсутствие этого оператора при наличии СУММА или КОЛИЧЕСТВО вызовет ошибку выполнения запроса.
Типичные ошибки и оптимизация
Одна из самых частых ошибок — это выборка лишних полей. Разработчики часто пишут ВЫБРАТЬ * или выбирают все поля табличной части, когда нужны только два-три реквизита. Это увеличивает объем передаваемых данных по сети и расходует оперативную память сервера приложений.
Еще одна проблема — отсутствие индексов. Если вы часто делаете отбор по какому-то специфическому реквизиту табличной части (например, по серийному номеру), убедитесь, что в конфигураторе для этого поля установлен флаг Индексирование. Без этого база данных будет выполнять полное сканирование таблицы, что очень медленно.
Также стоит упомянуть о проблеме блокировок. При чтении данных из табличных частей в момент, когда этот документ активно редактируется другим пользователем, ваш запрос может встать в очередь ожидания. Для отчетов, где актуальность данных "здесь и сейчас" не критична, можно использовать режим чтения НЕЖЕСТКОЕ БЛОКИРОВАНИЕ или чтение из временных таблиц.
⚠️ Внимание: Интерфейс и возможности платформы 1С могут обновляться. Проверяйте актуальные настройки индексации и права доступа в вашей версии конфигурации, так как старые инструкции могут не учитывать новые механизмы оптимизации СУБД.
Помните, что запрос к табличной части — это по сути запрос к обычной таблице базы данных, просто с длинным именем. Понимание этого факта помогает проще отлаживать сложные выборки. Используйте инструмент "Консоль запросов" для проверки планов выполнения и анализа времени работы ваших алгоритмов.
Как ускорить медленный запрос?
Попробуйте добавить условие отбора по периоду или организации. Часто именно отсутствие фильтра по дате заставляет систему перебирать весь архив документов за годы работы.
Часто задаваемые вопросы (FAQ)
Можно ли сделать запрос к табличной части без указания конкретного документа?
Да, можно. Если в условии ГДЕ не ограничивать выборку по полю Ссылка, запрос вернет строки табличных частей всех документов этого вида в базе данных. Это часто используется в общих отчетах по продажам или движению товаров.
Почему запрос возвращает дубли строк?
Чаще всего это происходит при неправильном соединении (JOIN) таблиц, когда условие соединения не является уникальным. Также дубли могут возникать, если в самой конфигурации документ содержит несколько одинаковых строк, и вы не делаете группировку.
Как обратиться к реквизиту табличной части в коде 1С?
В коде на встроенном языке путь выглядит так: Объект.Товары.Номенклатура. В запросе путь указывается через точку после алиаса таблицы: Товары.Номенклатура. Синтаксис немного отличается, но логика иерархии сохраняется.
Можно ли обновлять данные в табличной части через запрос?
Нет, язык запросов 1С предназначен только для чтения данных (оператор ВЫБРАТЬ). Для изменения данных необходимо получать объект документа в коде, модифицировать его табличную часть и записывать объект обратно в базу.
Что делать, если имя табличной части изменилось в новой версии?
При обновлении конфигурации имена таблиц могут меняться. Всегда используйте автоподстановку в конфигураторе или консоли запросов. Если вы храните текст запроса в виде строки в коде, его придется вручную актуализировать после обновления платформы.