При работе с типовыми конфигурациями (особенно такими как УПП или КА 1.1) программисты часто сталкиваются с огромными, «дикими» запросами. Такие запросы могут занимать сотни строк, содержать десятки временных таблиц и вложенных соединений. Попытка открыть их в конструкторе часто заканчивается ошибкой или неполным отображением данных. Разберем пошагово, как проанализировать такой запрос, понять его логику и успешно отладить.
В типовых отчетах текст запроса редко бывает статичным. Он собирается «как конструктор» из разных кусков строк в зависимости от условий, настроек пользователя и установленных флагов. Поэтому анализировать код в конфигураторе практически бесполезно — мы видим только заготовки. Рассмотрим, как получить реальный текст, который уходит на сервер SQL.
Для начала найдем в коде момент, где запрос выполняется. Обычно это методы Запрос.Выполнить() или Запрос.ВыполнитьПакет(). Поставим точку останова непосредственно на эту строку. Когда выполнение программы прервется, проанализируем объект Запрос в табло отладки:
Запрос.Текст. Если текст слишком длинный, отладчик может показать его не полностью.Запрос.Текст.Записать("C:\temp_query.txt").Запрос.Параметры. Без понимания того, что передано в &НачДата или &ДатаКон, логика может ускользнуть.Часто конструктор запросов выдает ошибку при попытке редактирования. Основная причина в типовых отчетах — использование расширений языка запросов для Системы Компоновки Данных (СКД). Это конструкции в фигурных скобках, например: {ДоговорКонтрагента.* КАК Покупатель}.
Конструктор внутри платформы не всегда корректно обрабатывает эти скобки, если запрос был модифицирован динамически. Чтобы «оживить» конструктор, выполним следующие действия:
{ } вместе с их содержимым.|).После этой очистки запрос станет «стандартным» и легко откроется в любой консоли запросов или конструкторе.
Рассмотрим структуру запроса из примера. Это классический алгоритм сопоставления оплат и отгрузок по методу ФИФО, который выполняется прямо в момент формирования отчета. Проанализируем, зачем здесь столько временных таблиц:
Таблицы остатков и оборотов. Сначала запрос собирает данные по взаиморасчетам из разных регистров (ВзаиморасчетыСКонтрагентами и ВзаиморасчетыСКонтрагентамиПоДокументамРасчетов). Это нужно, чтобы учесть разные настройки ведения учета по договорам.
Поиск «границы» оплаты. Самая сложная часть запроса занимается поиском первого неоплаченного документа. Логика такова:
Проанализируем фрагмент кода, отвечающий за это:
ВЫБРАТЬ
ВзаиморасчетыОиО.ДоговорКонтрагента,
ВзаиморасчетыОиО.Сделка,
МИНИМУМ(ВзаиморасчетыОиО.Регистратор) КАК ПервыйРегистратор
ИЗ
ВзаиморасчетыОиО КАК ВзаиморасчетыОиО
ГДЕ
ВзаиморасчетыОиО.Период >= &ДатаГраницы
СГРУППИРОВАТЬ ПО
ВзаиморасчетыОиО.ДоговорКонтрагента,
ВзаиморасчетыОиО.Сделка
Если в коде используется МенеджерВременныхТаблиц, это дает нам мощный инструмент для отладки. Проанализируем ситуацию: запрос поместил данные в таблицу ВзаиморасчетыСКонтрагентамиОборотыНаДатуКон. Мы можем посмотреть содержимое этой таблицы в любой момент после выполнения запроса.
Для этого в отладчике можно создать новый временный запрос, привязать его к менеджеру и выполнить:
НовыйЗапрос = Новый Запрос;
НовыйЗапрос.МенеджерВременныхТаблиц = Запрос.МенеджерВременныхТаблиц;
НовыйЗапрос.Текст = "ВЫБРАТЬ * ИЗ ВзаиморасчетыСКонтрагентамиОборотыНаДатуКон";
Результат = НовыйЗапрос.Выполнить().Выгрузить();
Теперь в переменной Результат мы видим промежуточные данные, что позволяет выяснить, на каком этапе «отваливаются» нужные записи.
Если запрос кажется слишком сложным, используем метод «разделяй и властвуй». Выпишем на лист бумаги или в текстовый файл названия всех временных таблиц в порядке их появления. Выясним роль каждой:
Проанализируем условия соединений. Если мы видим ВНУТРЕННЕЕ СОЕДИНЕНИЕ, помним: если в одной из таблиц нет данных по конкретному контрагенту, он исчезнет из всего отчета. Это самая частая причина «пустых» отчетов при наличии данных в регистрах.
Для эффективной работы рекомендуем использовать специализированные консоли запросов (например, от «Инструментов разработчика»), которые умеют работать с пакетами запросов и отображать содержимое всех временных таблиц одним нажатием кнопки. Это гораздо быстрее, чем вручную переписывать запросы в отладчике.
Также важно понимать архитектуру конфигурации. Если запрос обращается к РегистрНакопления.Продажи.Обороты и одновременно к РегистрСведений.КурсыВалют, значит, отчет пытается привести данные к одной валюте. Обратите внимание на соединение по периоду: часто курс берется на дату документа, что требует среза последних на каждую дату (в запросе это обычно реализуется через вложенный запрос с максимумом даты).
Помните, что анализ таких «монструозных» конструкций — это навык, который приходит с опытом. Главное — не пытаться охватить весь запрос целиком, а разбирать его по одной временной таблице за раз.