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

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

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

Особенности структуры таблиц в 1С

Проанализируем базовый принцип хранения данных. В 1С справочник — это не одна плоская таблица. Каждый справочник представлен основной таблицей (шапкой), а каждая его табличная часть — это отдельная физическая таблица в базе данных. Связь между ними осуществляется по уникальному идентификатору, который в 1С называется Ссылка. Рассмотрим пример: если у нас есть справочник Контрагенты с табличной частью КонтактныеЛица, то в SQL-представлении это будут две разные таблицы, где табличная часть содержит поле Ссылка, указывающее на владельца записи.

Подсчет количества записей в табличной части

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


ВЫБРАТЬ
    ТЧ.Ссылка КАК ДокументСсылка,
    КОЛИЧЕСТВО(ТЧ.НомерСтроки) КАК КоличествоСтрок
ИЗ
    Справочник.МойСправочник.ИмяТабличнойЧАсти КАК ТЧ
СГРУППИРОВАТЬ ПО
    ТЧ.Ссылка

Важный нюанс: результат выполнения запроса в 1С — это объект РезультатЗапроса. Чтобы получить из него конкретное число, у нас есть два пути:

  1. Использовать выборку: Запрос.Выполнить().Выбрать(). В этом случае нужно вызвать метод Следующий(), чтобы обратиться к данным.
  2. Выгрузить результат в таблицу значений: Запрос.Выполнить().Выгрузить(). Это удобно, если данных немного и их нужно обработать программно.

Соединение шапки справочника и его табличной части

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

Второй, более профессиональный подход — явное использование конструкции ЛЕВОЕ СОЕДИНЕНИЕ. Рассмотрим пример:


ВЫБРАТЬ
    Спр.Наименование,
    ТЧ.ФизЛицо
ИЗ
    Справочник.ЛицевыеСчета КАК Спр
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЛицевыеСчета.СписокЖильцов КАК ТЧ
    ПО Спр.Ссылка = ТЧ.Ссылка

Проблема «исчезающих» строк и обработка NULL

Разберем типичную ошибку новичков при использовании ЛЕВОГО СОЕДИНЕНИЯ. Когда мы присоединяем вторую таблицу и накладываем условие на её поля в секции ГДЕ, наше левое соединение фактически превращается во внутреннее. Это происходит потому, что для тех записей, которых нет во второй таблице, значения полей будут NULL. Любое сравнение NULL с конкретным значением возвращает ложь, и строка отсекается из результата.

Проанализируем решение этой проблемы. Чтобы сохранить все записи из первой таблицы, условие по второй таблице нужно перенести непосредственно в конструкцию ПО (условие связи). Сравним два варианта:

Неправильно:


ГДЕ
    ЛицевыеСчета.ПометкаУдаления = ЛОЖЬ
    И ЛицевыеСчетаСписокЖильцов.ДатаОкончания = &ПустаяДата

Правильно:


ИЗ
    Справочник.ЛицевыеСчета КАК ЛицевыеСчета
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЛицевыеСчета.СписокЖильцов КАК СписокЖильцов
    ПО ЛицевыеСчета.Ссылка = СписокЖильцов.Ссылка
    И СписокЖильцов.ДатаОкончания = &ПустаяДата
ГДЕ
    ЛицевыеСчета.ПометкаУдаления = ЛОЖЬ

Работа с временными таблицами и арифметические операции

При построении сложных отчетов часто используется пакетное выполнение запросов с помещением промежуточных итогов во временные таблицы. Рассмотрим ситуацию, когда мы соединяем две временные таблицы и хотим сложить числовые показатели. Если во второй таблице данных для какой-то ссылки не нашлось, система вернет NULL. Помните: любая математическая операция с NULL (например, 100 + NULL) всегда дает результат NULL.

Для корректного суммирования необходимо использовать функцию ЕСТЬNULL. Она проверяет значение первого параметра, и если там NULL, подставляет значение второго параметра. Посмотрим на пример:


ВЫБРАТЬ
    ВТ1.Ссылка,
    ВТ1.Сумма1 + ЕСТЬNULL(ВТ2.Сумма2, 0) КАК ИтоговаяСумма
ИЗ
    ВТ_ПервыеДанные КАК ВТ1
    ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ВторыеДанные КАК ВТ2
    ПО ВТ1.Ссылка = ВТ2.Ссылка

Дополнительные рекомендации по оптимизации

Рассмотрим еще несколько важных моментов, которые помогут писать запросы в 1С более качественно:

Таким образом, переход от SQL к запросам 1С требует понимания метаданных системы. Использование явных соединений, грамотная работа с NULL и применение временных таблиц — это залог создания надежного и быстрого кода.

← На главную