Как в запросе 1С соединить таблицы по части текстового поля через оператор ПОДОБНО

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

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

Разберем подробно, как правильно извлечь часть строки, сформировать условие соединения через ПОДОБНО с использованием временных таблиц и обойти типичные ошибки при работе со строками неограниченной длины.

Принцип соединения таблиц по подстроке

Рассмотрим стандартную ситуацию: в первых документах в начале поля Содержание содержится ключевой код партии или ящика (например, первые 10–20 символов), за которым следует произвольный текст. Во вторых документах указан только этот код либо он входит в состав текста. Нам необходимо сопоставить строки обеих выборок.

Для корректного соединения необходимо соблюдать ключевые правила:

  1. Индексация функции ПОДСТРОКА: В языке запросов 1С нумерация символов всегда начинается с единицы (1). Указание 0 является синтаксической ошибкой или может приводить к платформозависимым сбоям при трансляции в SQL.
  2. Ограничение длины строк: Поля неограниченной длины нельзя напрямую сравнивать через оператор = или использовать в условиях соединения. Функция ПОДСТРОКА(Поле, 1, N) или ВЫРАЗИТЬ(Поле КАК СТРОКА(N)) приводит строку к фиксированной длине.
  3. Позиция шаблона и джокера: В условии ПО Таблица2.Текст ПОДОБНО Таблица1.Шаблон длинный текст должен находиться слева, а шаблон с подстановочным знаком % (джокером) — справа. Для поиска совпадения по началу строки к выделенной подстроке добавляется знак процента в конце: ПОДСТРОКА(Поле, 1, 10) + "%".

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

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


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

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

Разберем по шагам, как работает этот запрос:

  1. В первой таблице ВТ_ИсходныеТМЗ мы отбираем только нужные операции поступления и формируем поле ШаблонКода. Для этого берем первые 10 символов поля содержания и конкатенируем их со знаком процента: ПОДСТРОКА(..., 1, 10) + "%".
  2. Во второй части запроса выполняем ЛЕВОЕ СОЕДИНЕНИЕ виртуальной таблицы движений с нашей временной таблицей. В условии соединения проверяем, что поле Содержание таможенного документа начинается со значения шаблона.

Важно: Соединение больших таблиц по условию ПОДОБНО исключает возможность использования индексов на уровне СУБД (Hash Join или Merge Join) и приводит к полному сканированию данных (Nested Loop). При работе с большими объемами информации рекомендуется заранее выносить ключевые реквизиты (номера ящиков, артикулы, партии) в отдельные реквизиты документов или субконто.

Особенности получения оборотов по оборотным субконто

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

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

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


ВЫБРАТЬ
    ТиповойОбороты.Субконто1 КАК ОбъектСтроительства,
    ТиповойОбороты.Субконто2 КАК СтатьяЗатрат,
    СУММА(ТиповойОбороты.СуммаОборотДт) КАК ОборотДоПериода,
    0 КАК ОборотЗаПериод
ИЗ
    РегистрБухгалтерии.Типовой.Обороты(&НачПериодаОбороты, &КонПериодаОбороты, , Счет = &Счет, &ВидыСубконто, , , ) КАК ТиповойОбороты
СГРУППИРОВАТЬ ПО
    ТиповойОбороты.Субконто1,
    ТиповойОбороты.Субконто2

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ТиповойОбороты.Субконто1,
    ТиповойОбороты.Субконто2,
    0,
    СУММА(ТиповойОбороты.СуммаОборотДт)
ИЗ
    РегистрБухгалтерии.Типовой.Обороты(&НачПериода, &КонПериода, , Счет = &Счет, &ВидыСубконто, , , ) КАК ТиповойОбороты
СГРУППИРОВАТЬ ПО
    ТиповойОбороты.Субконто1,
    ТиповойОбороты.Субконто2

При использовании такого запроса в Системе компоновки данных (СКД) поля ресурсов автоматически агрегируются и выводятся в единую строку отчета по каждому объекту и каждой статье затрат без дублирования.

← На главную