Как вывести два независимых списка документов в параллельных колонках одного запроса

Программист Управленческий учет
← На главную

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

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

Метод 1: Искусственная нумерация через соединение таблиц

Рассмотрим основной способ решения задачи, который не зависит от особенностей конкретной СУБД. Суть метода заключается в том, чтобы пронумеровать записи в каждой выборке (поступления и расходы) отдельно, а затем соединить их по этому порядковому номеру.

Разберем этот процесс по шагам. Сначала подготовим первую временную таблицу с поступлениями, добавив в нее поле-константу для последующего подсчета:


ВЫБРАТЬ
    ПоступлениеВКассу.Ссылка КАК Ссылка,
    ПоступлениеВКассу.СуммаДокумента КАК Сумма,
    ПоступлениеВКассу.Дата КАК Дата,
    1 КАК ПолеДляСчетчика
ПОМЕСТИТЬ ВТ_Поступления_Подготовка
ИЗ
    Документ.ПоступлениеВКассу КАК ПоступлениеВКассу
ГДЕ
    ПоступлениеВКассу.Контрагент = &Контрагент
    И ПоступлениеВКассу.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания;

Теперь применим «хитрый трюк» для нумерации. Мы соединим таблицу саму с собой по условию Т1.Дата >= Т2.Дата. Количество записей, у которых дата меньше или равна текущей, и будет являться порядковым номером строки. Проанализируем этот запрос:


ВЫБРАТЬ
    Т1.Ссылка КАК ДокументПоступления,
    Т1.Сумма КАК СуммаПоступления,
    КОЛИЧЕСТВО(Т2.Ссылка) КАК НомерСтроки
ПОМЕСТИТЬ ВТ_Поступления_Итог
ИЗ
    ВТ_Поступления_Подготовка КАК Т1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Поступления_Подготовка КАК Т2
    ПО Т1.Дата >= Т2.Дата
СГРУППИРОВАТЬ ПО
    Т1.Ссылка,
    Т1.Сумма,
    Т1.Дата;

Аналогичные действия необходимо выполнить для второй таблицы (например, «Расходная накладная»). В итоге мы получим две временные таблицы, в каждой из которых есть уникальный номер строки (1, 2, 3...).

Завершающим этапом станет ПОЛНОЕ СОЕДИНЕНИЕ этих таблиц по номеру строки. Это позволит нам вывести документы в параллельных колонках, даже если их количество в разных списках не совпадает:


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

Важные нюансы метода нумерации по дате

При использовании этого метода крайне важно учитывать ситуацию, когда несколько документов имеют абсолютно одинаковый момент времени (вплоть до секунды). Если просто соединять по Дата >= Дата, такие документы получат одинаковый номер строки, и при финальном соединении возникнет дублирование («размножение») строк.

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

ПО (Т1.Дата > Т2.Дата ИЛИ (Т1.Дата = Т2.Дата И Т1.Ссылка >= Т2.Ссылка))

Такой подход гарантирует, что каждый документ получит свой уникальный инкрементный номер.

Метод 2: Использование функции АВТОНОМЕРЗАПИСИ

В более современных версиях платформы 1С v8.3 появилась возможность использовать функцию АВТОНОМЕРЗАПИСИ(). Это значительно упрощает текст запроса и повышает его читаемость. Выясним, как это работает на практике.

Функция работает только при помещении результата во временную таблицу. Посмотрим на пример кода:


ВЫБРАТЬ
    АВТОНОМЕРЗАПИСИ() КАК НомерСтроки,
    ПКО.Ссылка КАК Ссылка,
    ПКО.СуммаДокумента КАК Сумма
ПОМЕСТИТЬ ВТ_ПКО
ИЗ
    Документ.ПоступлениеВКассу КАК ПКО
УПОРЯДОЧИТЬ ПО
    ПКО.Дата;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    АВТОНОМЕРЗАПИСИ() КАК НомерСтроки,
    РН.Ссылка КАК Ссылка,
    РН.СуммаДокумента КАК Сумма
ПОМЕСТИТЬ ВТ_РН
ИЗ
    Документ.РасходнаяНакладная КАК РН
УПОРЯДОЧИТЬ ПО
    РН.Дата;

После подготовки таких таблиц мы также соединяем их через ПОЛНОЕ СОЕДИНЕНИЕ по полю НомерСтроки. Однако стоит помнить замечание опытных разработчиков: 1С не гарантирует, что АВТОНОМЕРЗАПИСИ() всегда будет начинаться с единицы во всех типах СУБД. Хотя для задачи сопоставления двух таблиц это не критично (главное, чтобы шаг был одинаковым), метод с расчетом номера через соединение (Метод 1) считается более «каноническим» и надежным для чистого SQL.

Производительность и ограничения

Нужно понимать, что метод нумерации через соединение ПО Т1.Дата >= Т2.Дата имеет квадратичную сложность — $O(n^2)$. Рассмотрим ситуацию: если у контрагента за период накопилось 1000 документов поступления, системе придется обработать 1 000 000 записей при формировании номеров.

Практические советы по оптимизации:

  1. Всегда накладывайте максимально жесткие фильтры (по контрагенту, организации, периоду) до того, как начнете нумеровать записи.
  2. Если данных очень много (десятки тысяч строк), лучше отказаться от формирования такого отчета в одном запросе. В этом случае правильнее будет использовать СКД (Систему компоновки данных) с двумя отдельными наборами данных и горизонтальной группировкой или реализовать параллельный вывод программно в коде модуля.
  3. Индексируйте временные таблицы по полю НомерСтроки перед финальным соединением, если в выборке более пары сотен строк.

Альтернативный подход через СКД

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

Однако, если требуется именно программное получение таблицы значений с четким соответствием «Строка 1 — Строка 1», описанные выше методы с временными таблицами остаются единственным эффективным инструментом в арсенале разработчика 1С.

← На главную