Как исправить ошибку «Таблица не найдена» в запросе 1С и оптимизировать вывод отчета

Программист Управленческий учет Торговля и дистрибуция
← На главную

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

Причина ошибки «Таблица не найдена»

Рассмотрим основной нюанс обращения к метаданным. В языке запросов 1С существует строгое правило именования таблиц, которое отличается от синтаксиса встроенного языка. Выясним причину возникновения ошибки в исходном коде автора:

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

Вместо ошибочного:


|Из
|Документы.РасходнаяНакладная

Необходимо использовать правильное обращение:


|Из
|Документ.РасходнаяНакладная КАК РасходнаяНакладная

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

Исправление логики группировки и работы с итогами

Проанализируем следующую ошибку в коде — использование секции СГРУППИРОВАТЬ ПО. В запросе автора указано: СГРУППИРОВАТЬ ПО Итого. Это синтаксически неверно по двум причинам:

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

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


Запрос.Текст = 
    "ВЫБРАТЬ
    |	РасходнаяНакладная.Водитель КАК Водитель,
    |	СУММА(РасходнаяНакладная.КолвоЗаявок) КАК КолвоЗаявок
    |ИЗ
    |	Документ.РасходнаяНакладная КАК РасходнаяНакладная
    |
    |СГРУППИРОВАТЬ ПО
    |	РасходнаяНакладная.Водитель";

Обратите внимание на использование КАК КолвоЗаявок. Это создание псевдонима (алиаса). Без него поле в результате запроса будет называться автоматически (например, КолвоЗаявокСумма), и метод Параметры.Заполнить(Выборка) в макете не сможет найти соответствие между полем запроса и параметром области макета.

Оптимизация производительности: отказ от метода «Выбрать»

Посмотрим на структуру процедуры ЗаполнитьТабДок. Автор сначала делает перебор всех документов через Документы.РасходнаяНакладная.Выбрать(), а затем выполняет отдельный запрос для получения итогов. Это крайне неэффективный подход, особенно на больших объемах данных.

Разберем, почему лучше использовать один запрос:

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

Работа с текстовыми полями в запросах

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

Однако, если поле имеет неограниченную длину (тип «Текст» в базе данных), при попытке группировки система выдаст ошибку. В этом случае проанализируем ситуацию и применим функцию ВЫРАЗИТЬ:


|ВЫБРАТЬ
|   ВЫРАЗИТЬ(РасходнаяНакладная.Комментарий КАК СТРОКА(150)) КАК КомментарийКратко
|...
|СГРУППИРОВАТЬ ПО
|   ВЫРАЗИТЬ(РасходнаяНакладная.Комментарий КАК СТРОКА(150))

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

Итоговый правильный пример кода

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


&НаСервереБезКонтекста
Процедура ЗаполнитьТабДок(ТабДок)
    ТабДок.Очистить();
    Макет = Отчеты.ОтчетПоЗаказам.ПолучитьМакет("Отчёт");
    
    ОблШапка = Макет.ПолучитьОбласть("Шапка");
    ОблЭлемент = Макет.ПолучитьОбласть("Элемент");
    ОблИтого = Макет.ПолучитьОбласть("Итого");
    
    ОблШапка.Параметры.ДатаОтчёта = Формат(ТекущаяДата(),"ДЛФ=DD" );
    ТабДок.Вывести(ОблШапка);
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	РасходнаяНакладная.Водитель КАК Водитель,
        |	СУММА(РасходнаяНакладная.КолвоЗаявок) КАК КолвоЗаявок
        |ИЗ
        |	Документ.РасходнаяНакладная КАК РасходнаяНакладная
        |
        |СГРУППИРОВАТЬ ПО
        |	РасходнаяНакладная.Водитель
        |ИТОГИ
        |	СУММА(КолвоЗаявок)
        |ПО
        |	ОБЩИЕ";
    
    Результат = Запрос.Выполнить();
    
    // Выводим детальные записи
    ВыборкаДетали = Результат.Выбрать(ОбходРезультатаЗапроса.Прямой);
    Пока ВыборкаДетали.Следующий() Цикл
        ОблЭлемент.Параметры.Заполнить(ВыборкаДетали);
        ТабДок.Вывести(ОблЭлемент);
    КонецЦикла;
    
    // Выводим итог (из общей группировки запроса)
    ВыборкаИтог = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    Если ВыборкаИтог.Следующий() Тогда
        ОблИтого.Параметры.Заполнить(ВыборкаИтог);
        ТабДок.Вывести(ОблИтого);
    КонецЕсли;
КонецПроцедуры

Важные моменты:

Соблюдение этих правил позволит вам создавать быстрые и стабильные отчеты, избегая ошибок исполнения на стороне сервера базы данных.

← На главную