Как работать со сложными запросами в 1С и что считается «сложным» на практике

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработчика 1С рано или поздно наступает момент, когда простые выборки из одного справочника перестают закрывать потребности бизнеса. Мы сталкиваемся с многостраничными текстами запросов, десятками временных таблиц и программной сборкой кода. В этой статье мы разберем, что именно делает запрос «сложным», с какими трудностями можно столкнуться в типовых конфигурациях вроде ЗУП или ERP, и как современные возможности платформы помогают элегантно решать задачи, которые раньше считались невыполнимыми.

Что такое сложный запрос в современных реалиях 1С

Для начинающего разработчика сложным может показаться даже обычное ЛЕВОЕ СОЕДИНЕНИЕ или использование вложенного запроса. Однако, как показывает практика опытных специалистов, настоящая сложность начинается там, где количество соединений заставляет «рябить в глазах», а структура запроса становится нелинейной. Проанализируем основные критерии сложности:

  1. Программная сборка текста: Когда запрос не является статичным куском текста, а собирается из фрагментов в зависимости от условий в коде. Разбирать такой запрос в консоли крайне затруднительно, так как приходится «вылавливать» итоговый текст в отладчике.
  2. Использование множества менеджеров временных таблиц: Это характерно для ЗУП 3.1 и ERP, где данные подготавливаются в одном месте, а используются совершенно в другом.
  3. Глубокая вложенность: Ситуации, когда условия фильтрации накладываются на результаты вложенных запросов пятого-шестого порядка.
  4. Объем пакета: Встречаются случаи (как упоминалось в практике), когда один пакет запроса содержит более 160 временных таблиц.

Рассмотрим забавный, но показательный пример запроса, который часто ставит в тупик даже тех, кто привык к сложным джойнам. Попробуем проанализировать, что вернет следующий код:


ВЫБРАТЬ
 СУММА(1)
ИЗ Справочник.Номенклатура

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

Проблема правого соединения и конструктора запросов

Существует мнение, что ПРАВОЕ СОЕДИНЕНИЕ — это признак «ручной работы» и особой любви к SQL. На самом деле, большинство разработчиков 1С стараются избегать его, так как ЛЕВОЕ СОЕДИНЕНИЕ визуально понятнее: мы берем основную таблицу и дополняем ее данными. Интересно, что в последних версиях платформы Конструктор запроса иногда сам может генерировать правые соединения при изменении порядка таблиц, что порой удивляет даже опытных специалистов. Мы рекомендуем всегда приводить соединения к левому типу для обеспечения читаемости кода другими участниками команды.

Оптимизация тяжелых запросов со множеством временных таблиц

Когда мы сталкиваемся с запросом, в котором количество временных таблиц исчисляется десятками или сотнями, основной проблемой становится производительность и нагрузка на TempDB. Рассмотрим шаги по оптимизации таких «монстров»:

Во-первых, проанализируем индексацию. Если временная таблица используется в последующих соединениях, она ОБЯЗАТЕЛЬНО должна быть проиндексирована по полям связи. Без этого СУБД выберет неоптимальный план, и время выполнения вырастет по экспоненте.


// Пример правильного создания временной таблицы с индексом
ВЫБРАТЬ
    Номенклатура,
    Склад,
    КоличествоОстаток
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, )
ИНДЕКСИРОВАТЬ ПО
    Номенклатура,
    Склад
;

Во-вторых, оценим целесообразность дробления. Если пакет слишком велик, имеет смысл выгрузить промежуточный результат в менеджер временных таблиц и выполнить расчет в несколько этапов, делая паузы для очистки ненужных данных. Это особенно актуально для механизмов расчета себестоимости.

Новые возможности: Оконные функции и рекурсия

Долгое время разработчики 1С жаловались на отсутствие функций, привычных по «чистому» SQL (например, в MS SQL Server или PostgreSQL). Однако платформа 8.3.20 и выше принесла долгожданные изменения. Разберем их подробнее:

  1. Рекурсивные запросы (CTE): Начиная с версии 8.3.20, мы можем строить иерархические отчеты без использования обхода в цикле. Это позволяет, например, одним запросом получить всё дерево спецификаций изделия или структуру подразделений.
  2. Оконные функции: В версиях 8.3.24 и 8.3.27 появились функции ROW_NUMBER(), RANK(), LAG() и LEAD().

Посмотрим на пример использования оконной функции для нумерации строк внутри групп, что раньше требовало сложного соединения таблицы самой с собой:


ВЫБРАТЬ
    Продажи.Номенклатура,
    Продажи.Период,
    Продажи.Сумма,
    ПОРЯДКОВЫЙ_НОМЕР() OVER (ПАРТИЦИЯ ПО Продажи.Номенклатура УПОРЯДОЧИТЬ ПО Продажи.Период) КАК НомерСтрокиВГруппе
ИЗ
    РегистрНакопления.ВыручкаИПродажи КАК Продажи

Этот механизм позволяет значительно упростить текст запроса, делая его короче и быстрее. Раньше для решения такой задачи приходилось использовать соединение по условию Т1.Период >= Т2.Период, что создавало колоссальную нагрузку на сервер при больших объемах данных.

Инструменты для разбора и отладки

Как же разбираться в чужих сложных запросах? Рассмотрим проверенный инструментарий:

Важный момент: Сложные запросы в типовых шаблонах RLS (ограничение доступа на уровне записей) — это отдельный вид искусства. Для их «вкуривания» рекомендуется использовать производительный режим RLS, который платформа предлагает в последних редакциях. Он заменяет динамическое добавление подзапросов на использование предварительно рассчитанных таблиц прав, что делает итоговый SQL-код гораздо прозрачнее.

Подводя итог, можно сказать, что сложные запросы — это неотъемлемая часть жизни 1С-программиста в сегменте Middle и Senior. Главное — не бояться их объема, активно использовать временные таблицы с индексами и осваивать новые возможности платформы, такие как оконные функции, которые позволяют превратить «простыню» кода в элегантное и быстрое решение.

← На главную