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

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

Написание запросов к базе данных — ключевой навык разработчика в среде 1С:Предприятие. На начальном этапе простые выборки из одного справочника или документа не вызывают сложностей. Однако при переходе к пакетам запросов, сложным соединениям таблиц и расчетам остатков разработчики часто сталкиваются с непониманием логики работы СУБД и ошибками производительности. Разберем по шагам, как выстроить системное понимание языка запросов 1С и перейти от простых выборок к оптимизированным пакетным алгоритмам.

Фундаментальные основы: чем отличаются соединения и объединения

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

  1. Соединения таблиц (СОЕДИНЕНИЕ / JOIN): связывают строки двух таблиц по горизонтали на основании заданного условия связи (ПО / ON). При внутреннем соединении (ВНУТРЕННЕЕ СОЕДИНЕНИЕ) в результат попадают только те строки, для которых нашлось соответствие в обеих таблицах. При левом внешнем соединении (ЛЕВОЕ СОЕДИНЕНИЕ) выбираются все строки из левой таблицы, а из правой подтягиваются совпадающие данные; если соответствия нет, поля правой таблицы заполняются значением NULL.
  2. Объединения таблиц (ОБЪЕДИНИТЬ / UNION): объединяют результаты двух независимых выборок по вертикали. Наборы полей в объединяемых запросах должны строго совпадать по количеству и типам данных. Оператор ОБЪЕДИНИТЬ по умолчанию удаляет дубликаты строк (аналог UNION DISTINCT в SQL), в то время как ОБЪЕДИНИТЬ ВСЕ сохраняет все строки, работая значительно быстрее за счет отсутствия дополнительной сортировки.

Фильтрация данных: разница между ГДЕ и ИМЕЮЩИЕ

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

  1. Секция ГДЕ (WHERE): фильтрует исходные записи до того, как к ним будут применены группировки и агрегатные функции (СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ).
  2. Секция ИМЕЮЩИЕ (HAVING): накладывает условие на уже сгруппированные данные и вычисленные агрегаты. В конструкторе запросов 1С это условие формируется на закладке «Условия», если в левой части выражения указана агрегатная функция.

Посмотрим на пример правильного использования обоих операторов в одном запросе:


ВЫБРАТЬ
    ПродажиОбороты.Номенклатура КАК Номенклатура,
    СУММА(ПродажиОбороты.КоличествоОборот) КАК ВсегоПродано
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК ПродажиОбороты
ГДЕ
    ПродажиОбороты.Номенклатура.Услуга = ЛОЖЬ
СГРУППИРОВАТЬ ПО
    ПродажиОбороты.Номенклатура
ИМЕЮЩИЕ
    СУММА(ПродажиОбороты.КоличествоОборот) > 100

Правила работы с виртуальными таблицами регистров

Выясним причину падения производительности при работе с регистрами. Платформа 1С предоставляет готовые виртуальные таблицы (Остатки, Обороты, СрезПервых, СрезПоследних). Главное правило при их использовании — передавать параметры отбора непосредственно в круглые скобки виртуальной таблицы, а не выносить их в блок ГДЕ.

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

Пошаговая декомпозиция и работа с пакетами запросов

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

  1. Первый шаг пакета: выбираем исходные данные из документов или справочников с жесткими отборами и помещаем их во временную таблицу.
  2. Второй шаг пакета: индексируем ключевые поля временной таблицы с помощью конструкции ИНДЕКСИРОВАТЬ ПО. Это исключает полное сканирование (Table Scan) при последующих соединениях.
  3. Третий шаг пакета: получаем данные из виртуальных таблиц регистров, передавая временную таблицу в качестве фильтра.
  4. Финальный запрос: соединяем подготовленные плоские временные таблицы и формируем итоговый результат.
  5. Очистка ресурсов: если временная таблица содержит большой объем данных и больше не нужна в пакете, вызываем команду УНИЧТОЖИТЬ для освобождения памяти СУБД.

Разберем пример эффективного пакетного запроса:


ВЫБРАТЬ
    ЗаказКлиентаТовары.Номенклатура КАК Номенклатура,
    СУММА(ЗаказКлиентаТовары.Количество) КАК Заказано
ПОМЕСТИТЬ ВТ_ТоварыЗаказа
ИЗ
    Документ.ЗаказКлиента.Товары КАК ЗаказКлиентаТовары
ГДЕ
    ЗаказКлиентаТовары.Ссылка = &СсылкаНаЗаказ
СГРУППИРОВАТЬ ПО
    ЗаказКлиентаТовары.Номенклатура

ИНДЕКСИРОВАТЬ ПО
    Номенклатура
;

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

////////////////////////////////////////////////////////////////////////////////
УНИЧТОЖИТЬ ВТ_ТоварыЗаказа

Практические рекомендации по выстраиванию процесса обучения

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

  1. Изучите основы нативного SQL: понимание базового синтаксиса T-SQL (операторы SELECT, WHERE, GROUP BY, HAVING, все виды JOIN) дает фундаментальное понимание того, во что транслируются запросы платформы 1С на уровне СУБД.
  2. Используйте специализированную литературу: для понимания теории реляционных баз данных изучите руководство Ицика Бен-Гана по основам T-SQL или книгу «Head First SQL». Для изучения специфики платформы обратитесь к пособиям Е. Ю. Хрусталевой по языку запросов и «Настольной книге 1С:Эксперта по технологическим вопросам».
  3. Создайте тестовую базу данных: разверните пустую или демонстрационную конфигурацию, наполните ее тестовыми данными и отрабатывайте сложные выборки в интерактивной консоли запросов. Анализируйте промежуточные временные таблицы и реальное поведение платформы при изменении структуры связей.
  4. Контролируйте типы и разыменование ссылок: избегайте обращений через точку к ссылочным полям (например, Документ.Контрагент.ОсновнойДоговор.Валюта), так как это порождает скрытые неявные соединения. Для полей составного типа всегда применяйте функцию ВЫРАЗИТЬ(Поле КАК Тип).
← На главную