Как в 1С 7.7 выбрать первые N элементов в запросе или ограничить выборку

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Разработчики, работающие с платформой 1С:Предприятие 7.7, часто сталкиваются с ограничением штатного языка запросов («черных запросов»), в котором отсутствует прямой аналог SQL-команд TOP или LIMIT. Задача — найти, к примеру, последние 10 документов определенного вида или одну самую свежую запись без указания жесткого периода — становится нетривиальной. Если период поиска заранее неизвестен и может составлять как месяц, так и несколько лет, стандартный запрос начнет сканировать всю базу данных, что приведет к колоссальным задержкам.

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

Метод 1. Прямые SQL-запросы через 1С++

Проанализируем самый эффективный и профессиональный способ решения задачи. Если ваша база данных работает на MS SQL Server, использование внешней компоненты 1С++ позволяет писать запросы на чистом SQL. Это снимает все ограничения встроенного языка 1С 7.7.

Разберем основные преимущества этого метода:

  1. Использование TOP: Вы можете напрямую указать SELECT TOP 10.
  2. Индексы: SQL-сервер использует индексы для сортировки, что делает поиск «с конца» мгновенным.
  3. Скорость: Данные передаются сразу в таблицу значений или индексированную таблицу.

Рассмотрим пример кода для получения последних 5 документов поступления:


// Создаем объект для работы с SQL
ЗапросSQL = СоздатьОбъект("ODBCRecordset");
ТекстЗапроса = "
|SELECT TOP 5
|    Журнал.IDDoc as [Док $Документ],
|    Журнал.IDDocDef as Док_вид
|FROM
|    _1SJOURN as Журнал
|WHERE
|    Журнал.IDDocDef = $ВидДокумента.ПоступлениеТоваров
|ORDER BY
|    Журнал.Date_Time_IDDoc DESC
|";
ТаблицаРезультатов = ЗапросSQL.ВыполнитьИнструкцию(ТекстЗапроса);

Этот метод позволяет избежать перебора всех записей, так как SQL-сервер просто берет первые 5 строк из соответствующего индекса журнала документов.

Метод 2. Использование метода ВыбратьДокументы с прерыванием цикла

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

Разберем, как реализовать обратный поиск по шагам:

  1. Устанавливаем обратный порядок выборки.
  2. Запускаем цикл получения документов.
  3. Внутри цикла используем счетчик и команду Прервать при достижении нужного количества.

Посмотрим на пример реализации:


Док = СоздатьОбъект("Документ.ПоступлениеТоваров");
// Параметры: ДатаНач, ДатаКон, ОбратныйПорядок(1)
Док.ВыбратьДокументы(,, 1); 

Счетчик = 0;
КоличествоНужных = 10;

Пока Док.ПолучитьДокумент() = 1 Цикл
    // Здесь можно добавить дополнительные условия фильтрации
    Счетчик = Счетчик + 1;
    Сообщить("Найден документ: " + Док.ТекущийДокумент());
    
    Если Счетчик >= КоличествоНужных Тогда
        Прервать; // Выходим, как только набрали нужное количество
    КонецЕсли;
КонецЦикла;

Важный момент: использование параметра 1 в методе ВыбратьДокументы заставляет систему идти от конца журнала к началу. Это позволяет мгновенно найти самые свежие записи даже в огромной базе без указания периода.

Метод 3. Функция-счетчик в стандартном запросе (Внимание: изврат!)

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

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

Тем не менее, для небольших справочников структура может выглядеть так:


Переменная Счетчик = 0;

Функция ОграничитьВыборку()
    Счетчик = Счетчик + 1;
    Если Счетчик <= 10 Тогда
        Возврат 1;
    Иначе
        Возврат 0;
    КонецЕсли;
КонецФункции

// В тексте запроса
|Условие(ОграничитьВыборку() = 1);

Вердикт: использовать только для маленьких таблиц, где производительность не критична.

Метод 4. Поиск периодических реквизитов

Если ваша задача — найти последнее значение цены, курса валюты или любого другого периодического реквизита, не используйте запросы. Для этого в 1С 7.7 существует специализированный объект Периодический.

Посмотрим на алгоритм работы:

  1. Создаем объект Периодический.
  2. Используем метод ИспользоватьОбъект для привязки к реквизиту справочника.
  3. Вызываем ВыбратьЗначения с флагом обратного порядка.

Этот метод работает моментально, так как обращается напрямую к таблице истории значений (_1SCONST) по индексу.

Метод 5. Работа через ADO (ActiveX Data Objects)

Если вам нужно выполнить быстрый запрос SELECT TOP, но вы не можете устанавливать ВК 1С++, можно воспользоваться стандартными средствами Windows — ADO. Этот метод позволяет подключиться к базе данных 1С (как к SQL, так и к DBF через провайдер Jet или VFPOLEDB) и выполнить произвольный запрос.

Рассмотрим особенности:

Подведем итоги

Выбор метода зависит от ваших технических возможностей и версии базы данных:

Помните, что в 1С 7.7 отсутствие периода в «черном» запросе — это всегда риск Full Scan. Всегда старайтесь ограничивать выборку либо на уровне SQL-сервера, либо через последовательное чтение объектов с выходом из цикла.

← На главную