Разработка и Конфигурация · 11 мин
Как сделать запрос к табличной части в 1С
Как сделать запрос к табличной части в 1С 8.3: синтаксис запроса, обращение к ТЧ документа и справочника, соединения, итоги, типовые ошибки и примеры кода.
Табличная часть — это отдельная таблица в базе данных 1С, связанная с родительским объектом (документом или справочником) через поле «Ссылка». К табличной части можно обращаться в запросе так же, как к любой другой таблице: через точку после имени объекта указывается имя табличной части. Например, Документ.РеализацияТоваровУслуг.Товары — это таблица табличной части «Товары» документа «РеализацияТоваровУслуг».
Такие запросы нужны постоянно: собрать товары из всех реализаций за период, посчитать суммы по строкам, найти документы, где встречается конкретная номенклатура, выгрузить состав табличной части в таблицу значений. Ниже разобраны синтаксис, типовые сценарии, соединения с шапкой документа, группировки и ошибки, которые чаще всего мешают получить корректный результат.
Как устроено обращение к табличной части в языке запросов
В языке запросов 1С табличная часть адресуется полным путём: тип объекта, имя объекта, имя табличной части. Общий шаблон выглядит так:
ВЫБРАТЬ
Товары.Номенклатура,
Товары.Количество,
Товары.Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ
Товары.Ссылка = &Ссылка
Псевдоним после КАК упрощает чтение и обязателен, если дальше таблица соединяется с другими. Поле Ссылка в табличной части всегда содержит ссылку на документ-владелец — именно через него строки привязываются к шапке.
У табличной части доступны все реквизиты, которые заданы в конфигураторе для этой ТЧ, плюс служебные поля: Ссылка и НомерСтроки. Поле НомерСтроки удобно, когда нужно сохранить порядок строк как в документе — для этого добавляют упорядочивание УПОРЯДОЧИТЬ ПО Товары.НомерСтроки.
Запрос к табличной части конкретного документа
Самая частая задача — получить строки табличной части одного известного документа. Ссылка передаётся параметром, чтобы запрос не сканировал всю таблицу:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| Товары.Количество КАК Количество,
| Товары.Цена КАК Цена,
| Товары.Сумма КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка
|УПОРЯДОЧИТЬ ПО
| Товары.НомерСтроки";
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Результат = Запрос.Выполнить().Выгрузить();
Метод Выгрузить() возвращает таблицу значений, которую удобно обходить циклом или выводить в форму. Если нужен построчный обход без загрузки всего результата в память, используют Выбрать() и цикл Пока Выборка.Следующий() Цикл.
Альтернатива без запроса — прямой обход коллекции ДокументОбъект.Товары. Он проще, но работает только с объектом, загруженным целиком, и не подходит для выборки по многим документам. Для массовой обработки запрос быстрее и не требует чтения объектов.
Выборка по многим документам и соединение с шапкой
Поля шапки (дата, контрагент, организация) не хранятся в табличной части — их нужно получать через поле Ссылка. Доступны два варианта: обращение через точку или явное соединение.
ВЫБРАТЬ
Товары.Ссылка.Дата КАК Дата,
Товары.Ссылка.Контрагент КАК Контрагент,
Товары.Номенклатура КАК Номенклатура,
Товары.Сумма КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ
Товары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И Товары.Ссылка.Проведен
Обращение через точку («разыменование») читается легче, но при большом числе полей шапки и сложных условиях надёжнее явное соединение с таблицей документа — оно даёт оптимизатору больше свободы и упрощает отладку:
ВЫБРАТЬ
Реализация.Номер КАК Номер,
Товары.Номенклатура КАК Номенклатура,
Товары.Сумма КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК Реализация
ПО Товары.Ссылка = Реализация.Ссылка
ГДЕ
Реализация.Проведен
И Реализация.Контрагент = &Контрагент
Группировка и итоги по строкам табличной части
Чтобы посчитать суммарное количество и сумму по каждой номенклатуре из всех документов за период, применяют агрегатные функции с группировкой:
ВЫБРАТЬ
Товары.Номенклатура КАК Номенклатура,
СУММА(Товары.Количество) КАК Количество,
СУММА(Товары.Сумма) КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ГДЕ
Товары.Ссылка.Проведен
И Товары.Ссылка.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
Товары.Номенклатура
Правила, которые здесь важно помнить: каждое неагрегатное поле из секции ВЫБРАТЬ должно быть перечислено в СГРУППИРОВАТЬ ПО, иначе запрос не выполнится. Если нужны итоги с детализацией (например, документы внутри номенклатуры), используют ИТОГИ ПО и обход выборки по группировкам.
Для отбора уже сгруппированных значений (например, только позиции с суммой больше порога) применяют секцию ИМЕЮЩИЕ СУММА(Товары.Сумма) > &Порог — обычное ГДЕ к агрегатам неприменимо.
- 1Определите таблицу табличной части и нужные реквизиты
- 2Добавьте фильтр по периоду и признаку Проведен через поле Ссылка
- 3Перечислите измерения в СГРУППИРОВАТЬ ПО, показатели оберните в СУММА()
- 4Проверьте результат в консоли запросов на паре документов
- 5Перенесите текст в модуль и подставьте параметры
Запрос к табличной части справочника и несколько табличных частей
У справочников синтаксис аналогичный: Справочник.Контрагенты.КонтактнаяИнформация. Разница в том, что у справочника вместо даты и проведения фильтруют по ПометкаУдаления и реквизитам владельца.
Если у документа несколько табличных частей (например, «Товары» и «Услуги»), объединять их соединением по ссылке нельзя — получится декартово произведение строк. Правильный приём — объединение через ОБЪЕДИНИТЬ ВСЕ с одинаковым набором полей:
ВЫБРАТЬ
Товары.Ссылка КАК Документ,
Товары.Номенклатура КАК Номенклатура,
Товары.Сумма КАК Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Услуги.Ссылка,
Услуги.Номенклатура,
Услуги.Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Услуги КАК Услуги
Состав и типы полей в обеих частях объединения должны совпадать по порядку. Если в одной ТЧ нет нужного реквизита, подставляют значение-заглушку, например 0 или NULL, с последующей обработкой.
Способы получить данные табличной части
Подходит для выборок по многим документам, группировок и отчётов. Требует знания синтаксиса, но не читает объекты целиком.
Подходит для одного открытого документа в модуле объекта или формы. Для массовой обработки медленно, так как каждый объект читается из базы полностью.
Подходит для отчётов пользователям: тот же запрос к ТЧ плюс настройки отбора и оформления без кода.
Типичные ошибки и ограничения
Первая ошибка — забыть фильтр по проведённым документам. Табличные части помеченных на удаление и непроведённых документов физически хранятся в базе и попадут в выборку, исказив итоги. Всегда добавляйте условие Товары.Ссылка.Проведен или явно исключайте помеченные.
Вторая ошибка — соединение двух табличных частей одного документа по ссылке с целью «сложить» их. Строки перемножатся, и суммы вырастут в разы. Используйте ОБЪЕДИНИТЬ ВСЕ, как показано выше.
Третья группа проблем — производительность. Запрос к табличной части без условия по периоду или ссылке читает всю таблицу, что на крупных базах занимает заметное время и нагружает СУБД. Также избегайте обращений через точку к полям составного типа в условиях — это отключает использование индексов.
Проверка результата и инструменты отладки
До переноса запроса в код проверьте его в консоли запросов (встроенной в «Инструменты разработчика» или типовую обработку «Консоль запросов» из состава БСП). Сверьте итоговую сумму по выборке с суммой документа — это самый быстрый способ убедиться, что фильтры настроены верно.
Контрольные точки: число строк выборки для одного документа должно совпадать с числом строк табличной части в форме документа; сумма по полю Сумма — с итогом документа; при группировке сумма сгруппированных значений должна равняться сумме без группировки.
Как проверить результат
Равно числу строк ТЧ в форме документа
Строк больше или меньше — проверьте фильтр и соединения
Совпадает с итогом документа
Расхождение — в выборку попали лишние документы или строки перемножились
Запрос с фильтром периода выполняется быстро
Многократное замедление — нет фильтра, сканируется вся таблица
FAQ
Можно ли обратиться к табличной части, не зная имени документа?
Нет, в статическом тексте запроса имя объекта и табличной части указывается явно. Если имя известно только в момент выполнения, текст запроса формируют строкой через подстановку имени, предварительно проверив существование объекта через Метаданные.НайтиПоПолномуИмени().
Как получить табличную часть сразу по нескольким видам документов?
Через ОБЪЕДИНИТЬ ВСЕ: для каждого вида документа пишется свой подзапрос к его табличной части с одинаковым набором полей. Реквизиты, которых нет в части документов, заменяют заглушками (0 или NULL).
Почему в выборке появились строки удалённых документов?
Пометка удаления не удаляет строки табличной части физически. Добавьте условие Товары.Ссылка.Проведен для проведённых документов или НЕ Товары.Ссылка.ПометкаУдаления, если нужны и непроведённые.
Чем отличается поле Ссылка в табличной части от ссылки на строку?
Поле Ссылка — это ссылка на документ-владелец, одинаковая для всех строк ТЧ. Отдельной ссылки на строку не существует: строка идентифицируется парой «Ссылка + НомерСтроки».
Как вывести табличную часть в отчёт на СКД?
В наборе данных типа «Запрос» укажите таблицу табличной части как источник, добавьте нужные поля и связь с шапкой через Ссылка. Дальше отборы, группировки и оформление настраиваются стандартными средствами СКД без изменения кода.
Что важно запомнить
Табличная часть доступна в запросе как Документ.Имя.ИмяТЧ и связана с шапкой полем Ссылка. Фильтруйте по периоду и признаку Проведен, объединяйте несколько ТЧ через ОБЪЕДИНИТЬ ВСЕ, а результат перед использованием сверяйте с итогами документа.