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