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

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

Как читать запросы 1С: практическое руководство

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

Чтение чужого запроса 1С — ежедневная задача разработчика, внедренца и аналитика. Запросы встречаются в модулях документов, отчётах на СКД, обработчиках обмена и регламентных заданиях, и часто написаны без единого комментария. Умение быстро разобрать текст запроса экономит часы отладки и позволяет находить причины медленной работы и неверных данных.

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

Структура запроса: с чего начинать чтение

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

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

Отдельно проверьте слово РАЗЛИЧНЫЕ после ВЫБРАТЬ — оно убирает дубли строк и часто скрывает ошибку проектирования: дубли появились из-за неверного соединения, а автор «замаскировал» их различными. Если видите РАЗЛИЧНЫЕ вместе с соединением по детальной таблице — это повод разобраться глубже.

Соединения таблиц: как не потерять строки

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

При ЛЕВОЕ СОЕДИНЕНИЕ все строки левой таблицы останутся в результате, а поля правой будут NULL, если пары не нашлось. Это значит, что дальше по тексту выражения вида Правая.Сумма могут вернуть NULL, и автор должен был обработать это через ЕСТЬNULL(). Если обработки нет — возможны пустые значения в отчёте там, где ожидались нули.

ВНУТРЕННЕЕ СОЕДИНЕНИЕ отбрасывает строки без пары с обеих сторон. Если запрос «теряет» документы, первым делом проверьте, не стоит ли внутреннее соединение там, где логика требует левое.

Типичные ошибки при чтении соединений
01
Считать, что ЛЕВОЕ СОЕДИНЕНИЕ не меняет число строк: при дублях в правой таблице строки левой размножаются
02
Игнорировать условие соединения после ПО: лишнее условие сокращает результат, недостающее — создаёт декартово произведение
03
Не замечать NULL в полях правой таблицы и удивляться пустым итогам

Виртуальные таблицы и их параметры

Виртуальные таблицы — главная особенность языка запросов 1С. Конструкции вида РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Склад = &Склад) не существуют как физические таблицы: платформа строит их на лету по указанным параметрам. Читая такой фрагмент, сначала разберите параметры в скобках.

Первый параметр обычно — период или граница времени. Важно понимать, что передаётся: конкретная дата, Граница с включением или исключением момента. Ошибка в границе даёт расхождение остатков на один документ — классическая причина «не сходится на копейку».

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

Пакетные запросы и временные таблицы

Сложные запросы часто разбиты на пакет: несколько операторов, разделённых точкой с запятой. Первые запросы пакета создают временные таблицы (ПОМЕСТИТЬ ВТ_Имя), последующие их используют, а завершает пакет итоговая выборка.

Читайте пакет строго сверху вниз, как программу: каждая временная таблица — это промежуточный результат. Выпишите цепочку: что помещается в каждую ВТ, откуда данные берутся и где таблица уничтожается (УНИЧТОЖИТЬ). Если уничтожения нет — временная таблица живёт до конца пакета и занимает память.

Практический приём: в консоли запросов выполняйте пакет по частям, оставляя только один ПОМЕСТИТЬ и добавляя временный ВЫБРАТЬ * ИЗ ВТ_Имя. Так вы увидите содержимое каждого промежуточного шага и найдёте, на каком именно этапе данные «ломаются».

Как разобрать незнакомый запрос
  1. 1
    Скопируйте текст запроса в консоль запросов вместе с параметрами из кода
  2. 2
    Выпишите все источники данных и псевдонимы из предложения ИЗ
  3. 3
    Определите типы соединений и что происходит со строками без пары
  4. 4
    Разберите параметры виртуальных таблиц: периоды, границы, отборы
  5. 5
    Проследите цепочку временных таблиц от ПОМЕСТИТЬ до итоговой выборки
  6. 6
    Выполните запрос по частям и сверьте промежуточные результаты с ожиданиями

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

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

Консоль запросов (типовая в составе инструментов разработчика или внешние обработки) позволяет выполнить запрос с реальными параметрами и увидеть результат. Это основной инструмент проверки понимания: вы прочитали запрос, сформулировали ожидание, выполнили — и сверили.

Когда запрос работает медленно, читайте не только текст, но и план запроса на стороне СУБД. Технологический журнал с событием DBMSSQL или DBPOSTGRS показывает фактический SQL, а средства СУБД — план его выполнения. Полное сканирование большой таблицы в плане обычно означает отсутствие подходящего индекса или отбор не по индексированным полям.

Обращения через точку вида Док.Контрагент.ИНН — это скрытое соединение с таблицей справочника. Два-три таких разыменования в запросе по крупной таблице заметно замедляют выполнение: читая запрос, считайте количество точек в полях.
ПЗ
Практическое замечание

Особые конструкции: итоги, объединения, выражения

Предложение ИТОГИ ПО добавляет в результат группирующие строки — иерархию итогов. Читая такой запрос, помните: итоговые записи имеют ТипЗаписи отличный от детальной, и обход результата в коде должен это учитывать. ИТОГИ без группировки полей даёт одну общую итоговую строку.

ОБЪЕДИНИТЬ склеивает результаты двух выборок, ОБЪЕДИНИТЬ ВСЕ — без удаления дублей. Проверяйте соответствие полей по порядку и типам: платформа сопоставляет поля позиционно, и сдвиг на одну колонку даёт бессмысленный, но «работающий» результат.

Выражения ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ ... КОНЕЦ читайте как цепочку условий: важно, что стоит в ИНАЧЕ и что вернётся, если ни одно условие не сработало и ИНАЧЕ отсутствует — это будет NULL. Функции СУММА, КОЛИЧЕСТВО, МАКСИМУМ требуют группировки остальных полей; КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) считает уникальные значения и часто используется для подсчёта документов в выборке по строкам.

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

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

Число строк результата
Норма

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

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

Строк больше источника — размножение через соединение или ОБЪЕДИНИТЬ ВСЕ

Суммы по контрольному полю
Норма

Итог сходится с типовым отчётом по тому же регистру

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

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

Пустые значения в полях
Норма

NULL встречаются только там, где допустимо левое соединение

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

Пустые суммы или ссылки в обязательных полях

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

Чем чтение запроса в СКД отличается от обычного?

В схеме компоновки данных текст запроса — только основа: поверх него работают настройки отбора, группировок и ресурсов. Часть условий пользователь добавляет в настройках, поэтому итоговый SQL может отличаться от написанного текста. Анализируйте запрос вместе с макетом компоновки из консоли СКД или технологического журнала.

Как понять, какие параметры нужны запросу?

Все параметры отмечены символом «&». Выпишите их из текста и проверьте, что код устанавливает каждый через Запрос.УстановитьПараметр(). Неустановленный параметр вызовет ошибку при выполнении, а параметр неверного типа — неверный результат без сообщения об ошибке.

Почему запрос в консоли работает, а в коде — нет?

Чаще всего отличаются параметры: в консоли вы задаёте их вручную, а в коде они вычисляются. Другая причина — менеджер временных таблиц: если пакет использует ВТ, созданную ранее другим запросом, отдельное выполнение текста в консоли её не увидит.

Что делать, если запрос слишком большой для чтения целиком?

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

Как отличить медленный запрос по тексту, не запуская его?

Тревожные признаки: отборы по неиндексированным полям, соединения по выражениям и функциям, разыменования через несколько точек, СОЕДИНЕНИЕ без условия, выборка из таблицы движений без ограничения периода. Окончательный вывод делайте только по плану запроса на СУБД.

Итог

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

Читайте запрос от источников и соединений к полям выборки, разбирайте параметры виртуальных таблиц и цепочки временных таблиц, а понимание проверяйте выполнением по частям в консоли запросов и сверкой с контрольными итогами.