В консоли реализована универсальная функция для выполнения рекурсивных запросов.
Рекурсивный запрос — удобный способ выборки иерархических данных. Примеры рекурсивной выборки данных в 1С:Предприятие подробно рассмотрены в «Запрос против рекурсии или разузлование номенклатуры», «Транзитивное замыкание запросом» или далее по ссылкам в публикациях. Авторы предложили три варианта решения проблемы бесконечной рекурсии в графах с циклическими ссылками:
- Ограничивать количество рекурсивных циклов, предварительно вычислив их максимально возможное значение;
- Исключать циклические ссылки, проверяя пройденный путь, сохраняя его в виде строки кодов вершин графа;
- Исключать циклические ссылки, проверяя пройденный путь, сохраняя его во временной таблице.
Консоль позволяет опробовать любой из трех вариантов, для этого в консоли реализована специальная функция ВыполнитьРекурсивныйЗапрос(…). В функцию собраны идеи, описанные в вышеупомянутых публикациях:
- Рекурсивный запрос разбивается на три пакетных подзапроса: Начальный, Рекурсивный, Итоговый;
- Рекурсивный подзапрос повторяется в цикле. Условие выхода из рекурсивного цикла отличается и описано в особенностях функции;
- Начальные и промежуточные данные сохраняются во временные таблицы с индексом шага рекурсивного цикла;В тексте подзапросов к именам временных таблиц добавляются служебные окончания «__НАЧАЛО_РЕКУРСИИ__» или «__КОНЕЦ_РЕКУРСИИ__». Служебные окончания автоматически заменяются на соответствующий индекс шага рекурсивного цикла.
Встроенная в консоль функция имеет особенности:
- В конце начального подзапроса возвращается количество начальных данных;
- В конце рекурсивного подзапроса возвращается количество данных, отобранное для итоговой выборки;
- Рекурсивный цикл повторяется до тех пор, пока возвращаемое подзапросом число (количество записей) оказывается больше предыдущего числа (количества записей) — полученного на предыдущем шаге рекурсивного цикла.
- ВНИМАНИЕ! Не используйте в текстах Начального или Рекурсивного подзапросов стандартную функцию 1С:Предприятие ПРЕДСТАВЛЕНИЕ(), это приводит к бесконечной рекурсии — зависанию системы!
&НаСервере
Функция ВыполнитьРекурсивныйЗапрос(ЗНАЧ Параметр, ЗНАЧ Значение
, ЗНАЧ ТекстЗапросаИтог
, ЗНАЧ ТекстЗапросаРекурсия
, ЗНАЧ ТекстЗапросаНачало
, ЗНАЧ ШагРекурсииНачало = "__НАЧАЛО_РЕКУРСИИ__" // Подменяется в тексте запроса на предыдущий индекс шага рекурсии
, ЗНАЧ ШагРекурсииКонец = "__КОНЕЦ_РЕКУРСИИ__" // Подменяется в тексте запроса на текущий индекс шага рекурсии
, ЗНАЧ ЗапросМаксимальноеКоличествоЗаписей = "ВЫБРАТЬ 0;" // для предотвращения бесконечных рекурсий, 0 - без ограничений
, ЗНАЧ РежимОтладки = Ложь ) Экспорт
Если СокрЛП(ШагРекурсииНачало)="" тогда
ШагРекурсииНачало = "__НАЧАЛО_РЕКУРСИИ__"
КонецЕсли;
Если СокрЛП(ШагРекурсииКонец)="" тогда
ШагРекурсииКонец = "__КОНЕЦ_РЕКУРСИИ__"
КонецЕсли; ТекВремя = ТекущаяДата();
Если РежимОтладки тогда
Сообщить(Формат(ТекВремя, "ДЛФ=T") + ", СТАРТ запроса",СтатусСообщения.Информация);
КонецЕсли;
Запрос = Новый Запрос();
// Менеджер временных таблиц необходим для сохранения в памяти промежуточных таблиц рекурсии
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц();
// ИндексРекурсии для генерации шага рекурсии в имени таблицы
ИндексРекурсии = 0;
// Если начальный запрос пустой, выполним только итоговый запрос
Если ТекстЗапросаНачало<>Неопределено И ТекстЗапросаНачало<>"" тогда
// Выход из рекурсии, когда количество записей в итоговой теблице перестанет прибавляться
СтароеКоличествоЗаписей = 0;
НовоеКоличествоЗаписей = 0;
// Заменим в начальном подзапросе имена таблиц, указав начальный шаг рекрсии
Запрос.Текст = СтрЗаменить(ТекстЗапросаНачало, ШагРекурсииНачало, Формат(ИндексРекурсии, "ЧН=0; ЧГ=0"));
Если Параметр<>Неопределено И Параметр<>"" тогда
Запрос.УстановитьПараметр(Параметр, Значение);
КонецЕсли;
// Выполним начальный подзапрос
Попытка РезультатЗапроса = Запрос.Выполнить();
Исключение ВызватьИсключение "Ошибка в НАЧАЛЬНОМ подзапросе: " + ОписаниеОшибки() + " !ВНИМАНИЕ! Ключевое слово '"+ШагРекурсииНачало+"' заменено на '"+Формат(ИндексРекурсии, "ЧН=0; ЧГ=0")+"'";
КонецПопытки;
// Если рекурсивный запрос пустой, выполним только итоговый запрос
Если ТекстЗапросаРекурсия<>Неопределено И ТекстЗапросаРекурсия<>"" тогда
// Определим указанное в парамтрах максимальное допустимое количество шагов рекурсивного подзапроса
МаксимальноеКоличествоРекурсий=0;
Если ЗапросМаксимальноеКоличествоЗаписей<>Неопределено И ЗапросМаксимальноеКоличествоЗаписей<>"" тогда
ЗапросКоличества = Новый Запрос();
ЗапросКоличества.Текст = ЗапросМаксимальноеКоличествоЗаписей;
Попытка
РезультатЗапросаКоличества = ЗапросКоличества.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапросаКоличества.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
МаксимальноеКоличествоРекурсий = ВыборкаДетальныеЗаписи.Получить(0);
Если ТипЗнч(МаксимальноеКоличествоРекурсий)<>Тип("Число") тогда
Сообщить("Запрос '"+ЗапросМаксимальноеКоличествоЗаписей+"' для ограничения максимального количества записей должен быть пустым, либо возвращать число!" ,СтатусСообщения.Внимание);
МаксимальноеКоличествоРекурсий=1;
КонецЕсли;
КонецЕсли;
Исключение
Сообщить("Запрос для ограничения максимального количества записей рекурсии выполнен с ошибкой:" + ОписаниеОшибки() ,СтатусСообщения.Внимание);
МаксимальноеКоличествоРекурсий=1;
КонецПопытки;
КонецЕсли;
// Определим количество записей полученное в начальном подзапросе
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
НовоеКоличествоЗаписей = ВыборкаДетальныеЗаписи.Получить(0);
Если ТипЗнч(НовоеКоличествоЗаписей)<>Тип("Число") тогда
Сообщить("Начальный подзапрос должен возвращать количество записей в начальной выборке! НАПРИМЕР: 'ВЫБРАТЬ КОЛИЧЕСТВО (*) ИЗ ИтоговаяТаблица"+ШагРекурсииНачало+"' " ,СтатусСообщения.Внимание);
НовоеКоличествоЗаписей=1;
КонецЕсли;
КонецЕсли;
Если РежимОтладки тогда
ТекВремя=ТекущаяДата();
Сообщить(Формат(ТекВремя, "ДЛФ=T") + ", выполнен НАЧАЛЬНЫЙ подзапрос, количество записей: "+НовоеКоличествоЗаписей,СтатусСообщения.Информация);
КонецЕсли;
// Основной Ц И К Л рекурсии, пока увеличивается количество записей
Пока НовоеКоличествоЗаписей > СтароеКоличествоЗаписей
И (МаксимальноеКоличествоРекурсий=0 ИЛИ НовоеКоличествоЗаписей < МаксимальноеКоличествоРекурсий) цикл
// Сдвигаем количество записей и индекс рекурсии
СтароеКоличествоЗаписей = НовоеКоличествоЗаписей;
ИндексРекурсии = ИндексРекурсии + 1;
// Заменим в рекурсивном подзапросе имена таблиц, указав текущий шаг рекрсии
Запрос.Текст = СтрЗаменить(ТекстЗапросаРекурсия, ШагРекурсииНачало, Формат(ИндексРекурсии-1, "ЧН=0; ЧГ=0"));
Запрос.Текст = СтрЗаменить(Запрос.Текст, ШагРекурсииКонец, Формат(ИндексРекурсии, "ЧН=0; ЧГ=0"));
Если Параметр<>Неопределено И Параметр<>"" тогда
Запрос.УстановитьПараметр(Параметр, Значение);
КонецЕсли;
// Выполним рекурсивный подзапрос
Попытка
РезультатЗапроса = Запрос.Выполнить();
Исключение
ВызватьИсключение "Ошибка в РЕКУРСИВНОМ подзапросе: " + ОписаниеОшибки() + " !ВНИМАНИЕ! Ключевые слова: '"+ШагРекурсииНачало+"' заменено на '"+Формат(ИндексРекурсии-1, "ЧН=0; ЧГ=0")+"', " + " '"+ШагРекурсииКонец+"' заменено на '"+Формат(ИндексРекурсии, "ЧН=0; ЧГ=0")+"'";
КонецПопытки;
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
// Определим новое количество записей, полученное в рекурсивном подзапросе
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
НовоеКоличествоЗаписей = ВыборкаДетальныеЗаписи.Получить(0);
Если ТипЗнч(НовоеКоличествоЗаписей)<>Тип("Число") тогда
Сообщить("Рекурсивный подзапрос должен возвращать количество записей в итоговой выборке! НАПРИМЕР: 'ВЫБРАТЬ КОЛИЧЕСТВО (*) ИЗ ИтоговаяТаблица"+ШагРекурсииНачало+"' " ,СтатусСообщения.Внимание);
НовоеКоличествоЗаписей=1;
КонецЕсли;
КонецЕсли;
Если РежимОтладки И ТекВремя<>ТекущаяДата() тогда
ТекВремя=ТекущаяДата();
Сообщить(Формат(ТекВремя, "ДЛФ=T") + ", выполнен " + ИндексРекурсии + " РЕКУРСИВНЫЙ подзапрос, количество записей: "+НовоеКоличествоЗаписей,СтатусСообщения.Информация);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
// Заменим в итоговом подзапросе имена таблиц, указав конечный шаг рекрсии
Запрос.Текст = СтрЗаменить(ТекстЗапросаИтог, ШагРекурсииКонец, Формат(ИндексРекурсии, "ЧН=0; ЧГ=0"));
Если Параметр<>Неопределено И Параметр<>"" тогда
Запрос.УстановитьПараметр(Параметр, Значение);
КонецЕсли;
// Выполним итоговый подзапрос
Попытка
РезультатЗапроса = Запрос.Выполнить();
Исключение
ВызватьИсключение "Ошибка в ИТОГОВОМ подзапросе: " + ОписаниеОшибки() + " !ВНИМАНИЕ! Ключевое слово '"+ШагРекурсииКонец+"' заменено на '"+Формат(ИндексРекурсии, "ЧН=0; ЧГ=0")+"'";
КонецПопытки;
Если РежимОтладки тогда ТекВремя=ТекущаяДата();
Сообщить(Формат(ТекВремя, "ДЛФ=T") + ", выполнен ИТОГОВЫЙ подзапрос",СтатусСообщения.Информация);
КонецЕсли;
Возврат РезультатЗапроса;
КонецФункции
Консоль выполняет рекурсивный запрос в одном из двух режимов:
- “Выполнить” — в стандартном режиме;
- “Выполнить запрос с указанием времени” — с указанием времени выполнения рекурсивного запроса в формате часы:минуты:секунды.
Пример тестовой таблицы (вставить перед начальным подзапросом)
///////////////////////////////////////////////////////////////////////////////
// ФОРМИРОВАНИЕ ТЕСТОВОЙ ТАБЛИЦЫ
ВЫБРАТЬ 0 КАК объект, 1 КАК субъект , "00" КАК с_объект, "01" КАК с_субъект
ПОМЕСТИТЬ таблица10
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 2 КАК субъект , "00" КАК с_объект, "02" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 3 КАК субъект , "00" КАК с_объект, "03" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 4 КАК субъект , "00" КАК с_объект, "04" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 5 КАК субъект , "00" КАК с_объект, "05" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 6 КАК субъект , "00" КАК с_объект, "06" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 7 КАК субъект , "00" КАК с_объект, "07" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 8 КАК субъект , "00" КАК с_объект, "08" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 9 КАК субъект , "00" КАК с_объект, "09" КАК с_субъект
ОБЪЕДИНИТЬ ВЫБРАТЬ 0 КАК объект, 10 КАК субъект , "00" КАК с_объект, "10" КАК с_субъект;
ВЫБРАТЬ 100+родитель.субъект КАК объект, 200+потомок.субъект КАК субъект
, "1"+родитель.с_субъект КАК с_объект, "2"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ таблица100 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;
ВЫБРАТЬ 200+родитель.субъект КАК объект, 300+потомок.субъект КАК субъект
, "2"+родитель.с_субъект КАК с_объект, "3"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ таблица1000 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;
ВЫБРАТЬ 300+родитель.субъект КАК объект, 400+потомок.субъект КАК субъект
, "3"+родитель.с_субъект КАК с_объект, "4"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ таблица10000 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;
ВЫБРАТЬ 400+родитель.субъект КАК объект, 500+потомок.субъект КАК субъект
, "4"+родитель.с_субъект КАК с_объект, "5"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ таблица100000 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;
ВЫБРАТЬ 500+родитель.субъект КАК объект, 600+потомок.субъект КАК субъект
, "5"+родитель.с_субъект КАК с_объект, "6"+потомок.с_субъект КАК с_субъект
ПОМЕСТИТЬ таблица1000000 ИЗ таблица10 КАК родитель, таблица10 КАК потомок;
ВЫБРАТЬ 000+объект КАК объект, 100+субъект КАК субъект , "0"+с_объект КАК с_объект
, "1"+с_субъект КАК с_субъект ПОМЕСТИТЬ таблица ИЗ таблица10
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ * ИЗ таблица100
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ * ИЗ таблица1000
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ * ИЗ таблица10000
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ПЕРВЫЕ 0 * ИЗ таблица100000
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ ПЕРВЫЕ 0 * ИЗ таблица1000000
// Циклическая ссылка
//0// ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ 301 КАК объект, 101 КАК субъект
//0// , "301" КАК с_объект, "101" КАК с_субъект
ИНДЕКСИРОВАТЬ ПО объект, субъект;
УНИЧТОЖИТЬ таблица10;
УНИЧТОЖИТЬ таблица100;
УНИЧТОЖИТЬ таблица1000;
УНИЧТОЖИТЬ таблица10000;
УНИЧТОЖИТЬ таблица100000;
УНИЧТОЖИТЬ таблица1000000;
// КОНЕЦ ФОРМИРОВАНИЯ ТЕСТОВОЙ ТАБЛИЦЫ
///////////////////////////////////////////////////////////////////////////////
Пример начального подзапроса
///////////////////////////////////////////////////////////////////////////////
// НАЧАЛЬНЫЙ ПОДЗАПРОС
ВЫБРАТЬ объект, субъект , с_объект, с_субъект
, 1 КАК уровень , "."+с_объект+"."+с_субъект+"." КАК путь
, "" КАК старый_путь
ПОМЕСТИТЬ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__
ИЗ таблица
ГДЕ объект=0;
//--------- служебная счасть ---------//
// 1.1. ПРОЙДЕННЫЕ УЗЛЫ
// для исключения бесконечной рекурсии
//3//ВЫБРАТЬ РАЗЛИЧНЫЕ объект, субъект
//3//ПОМЕСТИТЬ ПройденныеУзлы__НАЧАЛО_РЕКУРСИИ__
//3//ИЗ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__
//3//ОБЪЕДИНИТЬ
//3//ВЫБРАТЬ субъект КАК объект, субъект
//3//ИЗ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__
//3//ИНДЕКСИРОВАТЬ ПО 2,1;
// 1.2. ИТОГОВЫЕ ДАННЫЕ
ВЫБРАТЬ * ПОМЕСТИТЬ ИтоговаяТаблица__НАЧАЛО_РЕКУРСИИ__
ИЗ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__;
// 1.4. КОЛИЧЕСТВО ЗАПИСЕЙ
ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ ИтоговаяТаблица__НАЧАЛО_РЕКУРСИИ__;
// КОНЕЦ НАЧАЛЬНОГО ПОДЗАПРОСА
///////////////////////////////////////////////////////////////////////////////
Пример рекурсивного подзапроса
///////////////////////////////////////////////////////////////////////////////
// РЕКУРСИВНЫЙ ПОДЗАПРОС
ВЫБРАТЬ таблица.*, рекурсия.уровень+1 КАК уровень
, рекурсия.путь+таблица.с_субъект+"." КАК путь
, рекурсия.путь КАК старый_путь
ПОМЕСТИТЬ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__
ИЗ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__ КАК рекурсия
ВНУТРЕННЕЕ СОЕДИНЕНИЕ таблица ПО таблица.объект=рекурсия.субъект
// соединенние для исключения бесконечной рекурсии
//3//ЛЕВОЕ СОЕДИНЕНИЕ ПройденныеУзлы__НАЧАЛО_РЕКУРСИИ__ ПройденныеУзлы
//3// ПО ПройденныеУзлы.субъект=таблица.объект
//3// И ПройденныеУзлы.объект=таблица.субъект
ГДЕ ИСТИНА
//1// И рекурсия.уровень<8 // ограниечение количества уровней //2// И НЕ рекурсия.путь ПОДОБНО "%."+таблица.с_субъект+".%" //3// И ПройденныеУзлы.субъект ЕСТЬ NULL ;
//--------- служебная счасть ---------//
// 2.1. ПРОЙДЕННЫЕ УЗЛЫ // для исключения бесконечной рекурсии //3//ВЫБРАТЬ РАЗЛИЧНЫЕ ПройденныеУзлы.объект, Рекурсия.субъект //3//ПОМЕСТИТЬ ПройденныеУзлы__КОНЕЦ_РЕКУРСИИ__ //3//ИЗ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__ Рекурсия //3//ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПройденныеУзлы__НАЧАЛО_РЕКУРСИИ__ ПройденныеУзлы ПО ПройденныеУзлы.субъект=Рекурсия.объект //3//ОБЪЕДИНИТЬ //3//ВЫБРАТЬ субъект КАК объект, субъект ИЗ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__ //3//ИНДЕКСИРОВАТЬ ПО 2,1;
// 2.2. ИТОГОВЫЕ ДАННЫЕ ВЫБРАТЬ * ПОМЕСТИТЬ ИтоговаяТаблица__КОНЕЦ_РЕКУРСИИ__ ИЗ ИтоговаяТаблица__НАЧАЛО_РЕКУРСИИ__
ОБЪЕДИНИТЬ ВСЕ ВЫБРАТЬ * ИЗ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__ ;
// 2.3. ОСВОБОЖДЕНИЕ ПАМЯТИ
//3//УНИЧТОЖИТЬ ПройденныеУзлы__НАЧАЛО_РЕКУРСИИ__;
УНИЧТОЖИТЬ РекурсивнаяТаблица__НАЧАЛО_РЕКУРСИИ__;
УНИЧТОЖИТЬ ИтоговаяТаблица__НАЧАЛО_РЕКУРСИИ__;
// 2.4. КОЛИЧЕСТВО ЗАПИСЕЙ
ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ ИтоговаяТаблица__КОНЕЦ_РЕКУРСИИ__;
// КОНЕЦ РЕКУРСИВНОГО ПОДЗАПРОСА
///////////////////////////////////////////////////////////////////////////////
Пример итогового подзапроса
///////////////////////////////////////////////////////////////////////////////
// ИТОГОВЫЙ ПОДЗАПРОС
ВЫБРАТЬ //ПЕРВЫЕ 10
КОЛИЧЕСТВО(*)
// *
ИЗ ИтоговаяТаблица__КОНЕЦ_РЕКУРСИИ__
//УПОРЯДОЧИТЬ ПО объект, субъект, путь
;
//--------- служебная счасть ---------//
// 3.3. ОСВОБОЖДЕНИЕ ПАМЯТИ
//3//УНИЧТОЖИТЬ ПройденныеУзлы__КОНЕЦ_РЕКУРСИИ__;
УНИЧТОЖИТЬ РекурсивнаяТаблица__КОНЕЦ_РЕКУРСИИ__;
УНИЧТОЖИТЬ ИтоговаяТаблица__КОНЕЦ_РЕКУРСИИ__;
УНИЧТОЖИТЬ таблица;
// конец ИТОГОВЫЙ ПОДЗАПРОС
///////////////////////////////////////////////////////////////////////////////
В подзапросах отмечены комментариями:
//0// — пример циклической ссылки — ВНИМАНИЕ! Возможно зависание системы! Не убирайте данный комментарий, если в рекурсивный запрос не включен механизм исключения циклических ссылок.
//1// — пример ограничения количества шагов рекурсивного цикла.
//2// — пример исключения циклических ссылок через проверку пройденного пути сохраненного в виде строки кодов вершин графа.
//3// — (в разных местах запроса) пример исключения циклических ссылок через проверку пройденного пути сохраненного во временную таблицу.
Время работы рекурсивной выборки в зависимости от количества итоговых записей
Тест файловой СУБД, Core2Duo 2.40GHz, 4ГБ ОЗУ
Кол-во записей |
Время выполнение рекурсивного запроса (сек.) |
||
Без контроля |
Контроль и сохранение пройденного пути |
||
в строке | в таблице | ||
111 110 | 5 | 6 | 37 |
121 110 | 6 | 7 | 43 |
211 110 | 10 | 11 | 81 |
311 110 | 15 | 16 | 124 |
411 110 | 20 | 21 | 172 |
511 110 | 23 | 25 | 211 |
711 110 | 32 | 35 | 257 |
911 110 | 41 | 44 | 385 |
1 111 110 |
49 | 54 | 473 |
Тест на http://demo.1c.ru
Кол-во записей |
Время выполнение рекурсивного запроса (сек.) |
||
Без контроля |
Контроль и сохранение пройденного пути |
||
в строке | в таблице | ||
111 110 | 1 | 2 | 7 |
121 110 | 1 | 2 | 7 |
211 110 | 1 | 4 | 9 |
311 110 | 3 | 5 | 9 |
411 110 | 3 | 6 | 11 |
511 110 | 4 | 7 | 12 |
711 110 | 5 | 9 | 15 |
911 110 | 10 | 11 | 17 |
1 111 110 |
11 | 11 | 20 |