Развернуть дерево спецификаций быстро

23.10.18

Разработка - Математика и алгоритмы

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

Скачать исходный код

Наименование Файл Версия Размер
Развернуть дерево спецификаций быстро
.epf 54,40Kb
16
.epf 2018-10-25 54,40Kb 16 Скачать

Суть метода

  Метод заключается в параллельном получении составов различных изделий по уровням дерева и помещение результата в кэш. Таким образом, к базе данных выполняется n-запросов, где <= Максимальная уровень глубины изделия.

Особенности метода

  • алгоритм позволяет получить составы в том случае, если не используются номенклатурные узлы;
  • в исходных комплектующих в полях Номенклатура, ХарактеристикаНоменклатуры должны быть значения типа СправочникСсылка.Номенклатура и СправочникСсылка.ХарактеристикиНоменклатуры соответственно, в противном случае там будет null;
  • не использует спецификации, явно указанные в исходных комплектующих (не стоит галка Использовать вид воспроизводства);
  • основные спецификации номенклатуры получаются на дату актуальных движений(параметр Период не указан);
  • используется алгоритм определения наиболее подходящих спецификаций подобно процедуре общего модуля УправлениеПроизводством.ОпределитьСпецификациюПоУмолчанию().

Описание алгоритма

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

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

Обработка-пример демонстрирует скорость работы данного подхода. Все процедуры алгоритма указаны в модуле обработке.

Тестировалось на платформах 8.2.13, 8.3.11. Конфигурация УПП 1.3.111.

Спецификации быстро дерево

См. также

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

10000 руб.

02.09.2020    125088    683    389    

732

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    16611    skovpin_sa    14    

101

MS SQL Server: изучаем планы запросов

Запросы HighLoad оптимизация Запросы Бесплатно (free)

Многие знают, что для ускорения работы запроса нужно «изучить план». При этом сам план обычно обескураживает: куча разноцветных иконок и стрелочек; ничего не понятно, но очень интересно! Аналитик производительности Александр Денисов на конференции Infostart Event 2021 Moscow Premiere рассказал, как выполняется план запроса и что нужно сделать, чтобы с его помощью находить проблемы производительности.

20.06.2023    17076    Филин    37    

114

Все консоли запросов для 1С

Запросы Инструментарий разработчика Бесплатно (free)

Список всех популярных обработок.

17.03.2023    37588    kuzyara    87    

181

Идентификатор объекта в запросе. Вы этого хотели?

Запросы Механизмы платформы 1С Платформа 1С v8.3 Запросы Бесплатно (free)

В платформе 8.3.22 появилась возможность получать идентификатор в запросе. Лично я ждал этого давно, но по итогу ждал большего. Что не так?

12.01.2023    41810    dsdred    26    

97

Практическая шпаргалка по новым возможностям языка запросов 1С

Механизмы платформы 1С Запросы Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

В предлагаемой статье решил привести примеры применения новых возможностей языка запросов 1С, начиная с версии платформы 8.3.20.

21.11.2022    23924    quazare    36    

122
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. пользователь 24.10.18 11:59
Сообщение было скрыто модератором.
...
2. RustIG 1595 24.10.18 19:01 Сейчас в теме
(0) молодцы! молодцы, что используете кэширование, хеш-таблицы, рекурсию - все это стандартные методы ускорения работы алгоритмов.
молодцы, что не заморочились одним большим запросом для получения дерева. такие и подобные задачи как раз так и решаются.
разработчики, берите на заметку.
3. Red_Devil 179 25.10.18 16:24 Сейчас в теме
{ВнешняяОбработка.ПостроитьДеревоСпецификаций_кэш.МодульОбъекта(589)}: Ошибка при вызове метода контекста (Выполнить)
РезультатЗапроса = Запрос.Выполнить();
по причине:
{(15, 87)}: Поле не найдено "ОриентировочныйСрокПоставки"
ЕСТЬNULL(ВЫРАЗИТЬ(СпецИсходныеКомплектующие.Номенклатура КАК Справочник.Номенклатура)<<?>>.ОриентировочныйСрокПоставки, 0) КАК СрокИзготовления,

ОриентировочныйСрокПоставки это типовой реквизит?
4. SITR-utyos 1420 25.10.18 17:00 Сейчас в теме
(3) Боюсь, что нет. Исправил этот момент
Функция теперь выглядит следующим образом:
// Функция заполняет кэш исходных комплектующих указанного перечня спецификаций
//
// Параметры:
//  КэшСпецификаций  - Соответствие - 
//                 <продолжение описания параметра>
//  МассивСпецификаций  - Массив, СписокЗначений - содержит в себе перечень Спецификаций,
// 							для которых необходимо получить исходные комплектующие
//  ВключатьПустые  - Булево - Определяет, необходимо ли фиксировать Спецификации без исходных комплектующих
//
// Возвращаемое значение:
//   Массив   - Массив спецификаций исходных комплектующих. Используется чтобы вызвать эту функцию повторно
//
Функция ПолучитьСоставСпецификаций(КэшСпецификаций, МассивСпецификаций, ВключатьПустые = Ложь) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	СпецификацииНоменклатуры.Ссылка КАК СпецификацияПродукции,
	|	СпецИсходныеКомплектующие.НомерСтроки КАК НомерСтроки,
	|	ВЫРАЗИТЬ(СпецИсходныеКомплектующие.Номенклатура КАК Справочник.Номенклатура) КАК Номенклатура,
	|	ВЫРАЗИТЬ(СпецИсходныеКомплектующие.Номенклатура КАК Справочник.Номенклатура).ВидВоспроизводства КАК НоменклатураВидВоспроизводства,
	|	ВЫРАЗИТЬ(СпецИсходныеКомплектующие.Номенклатура КАК Справочник.Номенклатура).ВидНоменклатуры КАК НоменклатураВидНоменклатуры,
	|	ВЫРАЗИТЬ(СпецИсходныеКомплектующие.ХарактеристикаНоменклатуры КАК Справочник.ХарактеристикиНоменклатуры) КАК ХарактеристикаНоменклатуры,
	|	СпецИсходныеКомплектующие.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
	|	ВЫБОР
	|		КОГДА СпецИсходныеКомплектующие.Номенклатура ССЫЛКА Справочник.Номенклатура
	|				И СпецИсходныеКомплектующие.ЕдиницаИзмерения <> ЗНАЧЕНИЕ(Справочник.ЕдиницыИзмерения.ПустаяСсылка)
	|			ТОГДА СпецИсходныеКомплектующие.Количество * СпецИсходныеКомплектующие.ЕдиницаИзмерения.Коэффициент / СпецИсходныеКомплектующие.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент
	|		ИНАЧЕ СпецИсходныеКомплектующие.Количество
	|	КОНЕЦ КАК Количество,
	|	ВЫБОР
	|		КОГДА СпецИсходныеКомплектующие.Ссылка ЕСТЬ NULL
	|			ТОГДА ИСТИНА
	|		ИНАЧЕ ЛОЖЬ
	|	КОНЕЦ КАК СпецификацияПустая
	|ПОМЕСТИТЬ ВТИсходныеКомплектующиеСпц
	|ИЗ
	|	Справочник.СпецификацииНоменклатуры КАК СпецификацииНоменклатуры
	|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СпецификацииНоменклатуры.ИсходныеКомплектующие КАК СпецИсходныеКомплектующие
	|		ПО СпецификацииНоменклатуры.Ссылка = СпецИсходныеКомплектующие.Ссылка
	|ГДЕ
	|	СпецификацииНоменклатуры.Ссылка В(&МассивСпецификаций)
	|	И ВЫБОР
	|			КОГДА &ВключатьПустые
	|				ТОГДА ИСТИНА
	|			ИНАЧЕ НЕ СпецИсходныеКомплектующие.Ссылка ЕСТЬ NULL
	|		КОНЕЦ
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	ВЫРАЗИТЬ(ВТИсходныеКомплектующиеСпц.Номенклатура КАК Справочник.Номенклатура) КАК Номенклатура,
	|	ВТИсходныеКомплектующиеСпц.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры
	|ПОМЕСТИТЬ ВТНоменклатураХарактеристики
	|ИЗ
	|	ВТИсходныеКомплектующиеСпц КАК ВТИсходныеКомплектующиеСпц
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	ОсновныеСпецификацииНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
	|	ОсновныеСпецификацииНоменклатурыСрезПоследних.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
	|	ОсновныеСпецификацииНоменклатурыСрезПоследних.СпецификацияНоменклатуры КАК СпецификацияНоменклатуры,
	|	3 КАК Приоритет
	|ПОМЕСТИТЬ ВТСпецификации
	|ИЗ
	|	ВТНоменклатураХарактеристики КАК ВТНоменклатураХарактеристики
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ОсновныеСпецификацииНоменклатуры.СрезПоследних(
	|				,
	|				(Номенклатура, ХарактеристикаНоменклатуры) В
	|					(ВЫБРАТЬ
	|						Таблица.Номенклатура,
	|						Таблица.ХарактеристикаНоменклатуры
	|					ИЗ
	|						ВТНоменклатураХарактеристики КАК Таблица)) КАК ОсновныеСпецификацииНоменклатурыСрезПоследних
	|		ПО ВТНоменклатураХарактеристики.Номенклатура = ОсновныеСпецификацииНоменклатурыСрезПоследних.Номенклатура
	|			И ВТНоменклатураХарактеристики.ХарактеристикаНоменклатуры = ОсновныеСпецификацииНоменклатурыСрезПоследних.ХарактеристикаНоменклатуры
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ОсновныеСпецификацииНоменклатурыСрезПоследних.Номенклатура,
	|	ВТНоменклатураХарактеристики.ХарактеристикаНоменклатуры,
	|	ОсновныеСпецификацииНоменклатурыСрезПоследних.СпецификацияНоменклатуры,
	|	4
	|ИЗ
	|	ВТНоменклатураХарактеристики КАК ВТНоменклатураХарактеристики
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ОсновныеСпецификацииНоменклатуры.СрезПоследних(
	|				,
	|				Номенклатура В
	|						(ВЫБРАТЬ
	|							Таблица.Номенклатура
	|						ИЗ
	|							ВТНоменклатураХарактеристики КАК Таблица)
	|					И ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК ОсновныеСпецификацииНоменклатурыСрезПоследних
	|		ПО ВТНоменклатураХарактеристики.Номенклатура = ОсновныеСпецификацииНоменклатурыСрезПоследних.Номенклатура
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ
	|	ОсновныеСпецификацииНоменклатурыСрезПоследних.Номенклатура,
	|	ВТНоменклатураХарактеристики.ХарактеристикаНоменклатуры,
	|	ОсновныеСпецификацииНоменклатурыСрезПоследних.СпецификацияНоменклатуры,
	|	5
	|ИЗ
	|	ВТНоменклатураХарактеристики КАК ВТНоменклатураХарактеристики
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ОсновныеСпецификацииНоменклатуры.СрезПоследних(
	|				,
	|				Номенклатура В
	|					(ВЫБРАТЬ
	|						Таблица.Номенклатура
	|					ИЗ
	|						ВТНоменклатураХарактеристики КАК Таблица)) КАК ОсновныеСпецификацииНоменклатурыСрезПоследних
	|		ПО ВТНоменклатураХарактеристики.Номенклатура = ОсновныеСпецификацииНоменклатурыСрезПоследних.Номенклатура
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	ВТСпецификации.Номенклатура,
	|	ВТСпецификации.ХарактеристикаНоменклатуры,
	|	ВТСпецификации.СпецификацияНоменклатуры
	|ПОМЕСТИТЬ ВТСпецификацииПоУмолчанию
	|ИЗ
	|	ВТСпецификации КАК ВТСпецификации
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
	|			ВТСпецификации.Номенклатура КАК Номенклатура,
	|			ВТСпецификации.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
	|			МИНИМУМ(ВТСпецификации.Приоритет) КАК Приоритет
	|		ИЗ
	|			ВТСпецификации КАК ВТСпецификации
	|		
	|		СГРУППИРОВАТЬ ПО
	|			ВТСпецификации.Номенклатура,
	|			ВТСпецификации.ХарактеристикаНоменклатуры) КАК МинимальныйПриоритет
	|		ПО ВТСпецификации.Номенклатура = МинимальныйПриоритет.Номенклатура
	|			И ВТСпецификации.ХарактеристикаНоменклатуры = МинимальныйПриоритет.ХарактеристикаНоменклатуры
	|			И ВТСпецификации.Приоритет = МинимальныйПриоритет.Приоритет
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	ВТИсходныеКомплектующиеСпц.СпецификацияПродукции КАК СпецификацияПродукции,
	|	ВТИсходныеКомплектующиеСпц.НомерСтроки,
	|	ВТИсходныеКомплектующиеСпц.Номенклатура,
	|	ВТИсходныеКомплектующиеСпц.НоменклатураВидВоспроизводства,
	|	ВТИсходныеКомплектующиеСпц.НоменклатураВидНоменклатуры,
	|	ВТИсходныеКомплектующиеСпц.ХарактеристикаНоменклатуры,
	|	ВТИсходныеКомплектующиеСпц.ЕдиницаИзмерения,
	|	ВТИсходныеКомплектующиеСпц.Количество,
	|	ВТИсходныеКомплектующиеСпц.СпецификацияПустая,
	|	ВТСпецификацииПоУмолчанию.СпецификацияНоменклатуры,
	|	ВЫБОР
	|		КОГДА ВТИсходныеКомплектующиеСпц.СпецификацияПродукции = ВТСпецификацииПоУмолчанию.СпецификацияНоменклатуры
	|			ТОГДА ИСТИНА
	|		ИНАЧЕ ЛОЖЬ
	|	КОНЕЦ КАК ЗацикливаниеСпецификации,
	|	ЕСТЬNULL(СпецВыходныеИзделия.ТочкаМаршрута.Подразделение, ЗНАЧЕНИЕ(Справочник.Подразделения.ПустаяСсылка)) КАК ЦехИзготовитель,
	|	СпецВыходныеИзделия.ТочкаМаршрута КАК ТочкаМаршрута
	|ИЗ
	|	ВТИсходныеКомплектующиеСпц КАК ВТИсходныеКомплектующиеСпц
	|		ЛЕВОЕ СОЕДИНЕНИЕ ВТСпецификацииПоУмолчанию КАК ВТСпецификацииПоУмолчанию
	|			ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.СпецификацииНоменклатуры.ВыходныеИзделия КАК СпецВыходныеИзделия
	|			ПО ВТСпецификацииПоУмолчанию.СпецификацияНоменклатуры = СпецВыходныеИзделия.Ссылка
	|				И ВТСпецификацииПоУмолчанию.Номенклатура = СпецВыходныеИзделия.Номенклатура
	|		ПО ВТИсходныеКомплектующиеСпц.Номенклатура = ВТСпецификацииПоУмолчанию.Номенклатура
	|			И ВТИсходныеКомплектующиеСпц.ХарактеристикаНоменклатуры = ВТСпецификацииПоУмолчанию.ХарактеристикаНоменклатуры
	|
	|УПОРЯДОЧИТЬ ПО
	|	ВТИсходныеКомплектующиеСпц.СпецификацияПродукции,
	|	ВТИсходныеКомплектующиеСпц.НомерСтроки
	|ИТОГИ ПО
	|	СпецификацияПродукции";
	// Устанавливаем параметры
	Запрос.УстановитьПараметр("МассивСпецификаций", МассивСпецификаций);
	Запрос.УстановитьПараметр("ВключатьПустые",		ВключатьПустые);
	РезультатЗапроса = Запрос.Выполнить();
	ВыборкаПоСпецификациям = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
	
	// Создадим таблицу такую же как колонки выборки
	СтруктураТаблицы = Новый ТаблицаЗначений;
	Для Каждого Колонка Из РезультатЗапроса.Колонки Цикл
		Если Колонка.Имя = "СпецификацияПродукции" Тогда
			Продолжить;
		КонецЕсли;
		
		ЗаполнитьЗначенияСвойств(СтруктураТаблицы.Колонки.Добавить(), Колонка);
		
	КонецЦикла;
	
	// Здесь будем хранить различные спецификации исходных комплектующих
	СпецификацииИсходныхКомплектующих = Новый ТаблицаЗначений;
	СпецификацииИсходныхКомплектующих.Колонки.Добавить("СпецификацияНоменклатуры");
	
	// Пройдемся по спецификациям и добавим их в кэш
	Пока ВыборкаПоСпецификациям.Следующий() Цикл
		
		Выборка = ВыборкаПоСпецификациям.Выбрать();
		ИсходныеКомплектующие = СтруктураТаблицы.СкопироватьКолонки();// Создаем Таблицу исходных комплетующих текущей специфиикации. Создаем НОВУЮ таблицу, это очень важно
		Пока Выборка.Следующий() Цикл
			// Спецификация пустая - прерываемся, чтобы таблица исходных комплектующих была пустой
			Если Выборка.СпецификацияПустая Тогда
				Прервать;
			КонецЕсли;
			
		    НоваяСтрока = ИсходныеКомплектующие.Добавить();
		    ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
			
			// Если обнаружено зацикливание - очищаем Спецификацию, чтобы это не обрабатывалось
			Если Выборка.ЗацикливаниеСпецификации Тогда
				Сообщить("Обнаружено зацикливание спецификации на изделие " + Выборка.Номенклатура, СтатусСообщения.Важное);
				НоваяСтрока.СпецификацияНоменклатуры = Справочники.СпецификацииНоменклатуры.ПустаяСсылка();
				Продолжить;
			КонецЕсли;
			
			// Если спецификацию еще не получали - добавим в список
			Если КэшСпецификаций.Получить(Выборка.СпецификацияНоменклатуры) = Неопределено Тогда
				НоваяСтрока = СпецификацииИсходныхКомплектующих.Добавить();
				НоваяСтрока.СпецификацияНоменклатуры = Выборка.СпецификацияНоменклатуры; 
			КонецЕсли;
		КонецЦикла;
		
		// Добавляем в кэш Спецификацию и еще исходные комплектующие в виде ТаблицыЗначений
		КэшСпецификаций.Вставить(ВыборкаПоСпецификациям.СпецификацияПродукции, ИсходныеКомплектующие);
		
	КонецЦикла;
	
	СпецификацииИсходныхКомплектующих.Свернуть("СпецификацияНоменклатуры");
	
	Возврат СпецификацииИсходныхКомплектующих.ВыгрузитьКолонку("СпецификацияНоменклатуры");
	
КонецФункции
Показать
Светлый ум; +1 Ответить
5. triviumfan 93 25.10.18 21:11 Сейчас в теме
(4) В ВТ "ВТИсходныеКомплектующиеСпц" и "ВТНоменклатураХарактеристики" в качестве поля "Номенклатура" после "Выразить()" могут быть NULL.
6. SITR-utyos 1420 26.10.18 07:37 Сейчас в теме
(5)
В ВТ "ВТИсходныеКомплектующиеСпц" и "ВТНоменклатураХарактеристики" в качестве поля "Номенклатура" после "Выразить()" могут быть NULL.

Согласен. Добавлено описание в раздел Особенности метода.
9. Светлый ум 406 22.07.22 08:22 Сейчас в теме
(4) + 1 Потестим в выходные
7. AlexDidenko 21.12.19 15:47 Сейчас в теме
В ERP 2.4 будет работать?
8. echo77 1881 21.12.19 15:50 Сейчас в теме
(7) Вряд ли, но реализованный подход думаю, можно будет использовать
10. user1572191 01.05.23 18:56 Сейчас в теме
Добрый день, может кто-нибудь обработку продать не за стартмани?
Оставьте свое сообщение