Как в запросе 1С реализовать одновременный обход таблицы с начала и с конца?

Программист
← На главную

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

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

Решение через нумерацию строк и соединение таблицы с самой собой

Этот метод является наиболее универсальным и мощным для решения поставленной задачи. Он позволяет получить все нужные пары (первая-последняя, вторая-предпоследняя и т.д.) в результате одного запроса. Разберем его по шагам.

  1. Подготовка и нумерация данных. Первым делом нам нужно поместить исходные данные во временную таблицу и, что самое главное, добавить к каждой строке ее порядковый номер. Для этого идеально подходят оконные функции, а именно ROW_NUMBER(). Также нам понадобится общее количество строк в таблице, которое мы можем получить с помощью агрегатной функции КОЛИЧЕСТВО(*).
  2. Соединение таблицы с самой собой (self-join). Это ядро нашего решения. Мы соединяем созданную временную таблицу саму с собой по специальному условию, которое и сформирует искомые пары.

Проанализируем логику условия соединения. Пусть у нас есть N строк. Для первой строки (номер 1) нам нужна последняя (номер N). Для второй (номер 2) — предпоследняя (номер N-1). В общем виде, для строки с номером i нам нужна строка с номером N - i + 1. Именно это правило мы и заложим в условие соединения.

Посмотрим на пример. Предположим, у нас есть табличная часть документа КоординатыГородов с колонкой Координата.

Запрос будет выглядеть следующим образом:


// Шаг 1: Помещаем данные во временную таблицу, нумеруем строки и считаем общее количество
ВЫБРАТЬ
    ТЧ.Координата,
    КОЛИЧЕСТВО(1) ПО (УПОРЯДОЧИТЬ ПО ТЧ.НомерСтроки) КАК НомерСтроки, // ROW_NUMBER()
    КОЛИЧЕСТВО(1) ПО () КАК ВсегоСтрок                          // COUNT(*)
ПОМЕСТИТЬ ПронумерованныеКоординаты
ИЗ
    Документ.КакойТоДокумент.КоординатыГородов КАК ТЧ
ГДЕ
    ТЧ.Ссылка = &СсылкаНаДокумент;

////////////////////////////////////////////////////////////////////////////////
// Шаг 2: Соединяем временную таблицу с самой собой для получения пар
ВЫБРАТЬ
    Т1.Координата КАК КоординатаНачало,
    Т2.Координата КАК КоординатаКонец,
    Т1.НомерСтроки
ИЗ
    ПронумерованныеКоординаты КАК Т1
        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПронумерованныеКоординаты КАК Т2
        ПО Т1.НомерСтроки = (Т1.ВсегоСтрок - Т2.НомерСтроки + 1)
ГДЕ
    // Условие, чтобы избежать дублирования пар (например, 1-10 и 10-1).
    // Мы берем только первую половину строк из левой таблицы.
    Т1.НомерСтроки <= Т1.ВсегоСтрок / 2
;

Разберем код подробнее:

Теперь в результате запроса мы имеем плоскую таблицу, где в каждой строке уже есть нужные нам данные: КоординатаНачало и КоординатаКонец. Дальнейшие вычисления по вашей формуле можно производить прямо в секции ВЫБРАТЬ этого же запроса.

Вопросы производительности: запрос против цикла

Часто возникает вопрос: что будет быстрее — такой "тяжелый" запрос или привычный цикл в коде 1С? Однозначного ответа нет, все зависит от объема данных.

Главный вывод: всегда проводите замеры производительности на данных, приближенных к реальным. Универсального рецепта нет, и выбор оптимального решения зависит от конкретной ситуации.

Альтернативный подход для гео-задач: PostgreSQL + PostGIS

Если ваша задача связана не просто с числами, а именно с географическими координатами, и в будущем планируется более сложная логика (построение маршрутов, поиск ближайших объектов, расчет расстояний по кривой Земли), стоит рассмотреть более профессиональные инструменты.

PostGIS — это расширение для СУБД PostgreSQL, которое добавляет поддержку гео-объектов и множество встроенных функций для пространственного анализа. Платформа 1С может работать с PostgreSQL, и для вызова специфичных функций PostGIS можно использовать прямые запросы к СУБД.

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

← На главную