Имя: Пароль:
1C
1С v8
Запрос на структуру дерева
0 alexei366
 
18.08.14
12:34
Здрасти, есть необходимость получить таблицу значений с 3-мя колонками : номенклатура , группа (в которую она входит вплоть до корня), уровень (уровень группы относительно корня).

Такс в начале у нас есть массив номенклатур;

Я разбил задачу на 2 части:
1) сначала получаю дерево значений, путем обхода массива номенклатур и делая запросы на родителя (мне кажется не очень эффективно). Тут наверно можно какнить 1-м запросом возможно но я пока ещё не совсем гуру в операторах языка запроса 1С.
Дерево получается такой же структуры как и справочник, но в нем только пути до наших номенклатур из массива (тоесть для 1 строки группы, могут быть подвязаны несколько строк номенклатур)

2) перевожу дерево значений в таблицу значений.

Вопрос:
Есть мысли как ускорить (написать по красоте) первую часть, или же как-то в 1 запросе всю шаурму сделать.
Дерево значений я использую для удобства, чтобы не вычислять в запросе родителя номенклатуры если таковой уже имеется в дереве, и чтоб потом по дереву удобней таблицу делать путем обхода строк номенклатур до корня дерева.
1 MaXpaT
 
18.08.14
12:42
ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Представление
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.Ссылка = &Ссылка
ИТОГИ ПО
    Ссылка ИЕРАРХИЯ
2 MaXpaT
 
18.08.14
12:43
оно?
3 alexei366
 
18.08.14
12:54
(2) Я не знаю, что в дает "ИТОГИ ПО", как отрабатывает?
4 alexei366
 
18.08.14
14:39
Корочь сделал так:
На входе только "МассивНоменклатуры", "МассивРазныхНом" не смотрите, он на будущее. Единственное Уровень в обратную сторону получился но для моих целей хватает (так хоть функцию "Уровень()" не использовал).



ТаблицаГрупп = Новый ТаблицаЗначений;
    ТаблицаГрупп.Колонки.Добавить("Группа", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
    ТаблицаГрупп.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
    ТаблицаГрупп.Колонки.Добавить("Уровень", Новый ОписаниеТипов("Число"));
        
    ЗапросРод = Новый Запрос;
    ЗапросРод.Текст = "ВЫБРАТЬ
    |    Номенклатура.Родитель,
    |    Номенклатура.Ссылка
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |    Номенклатура.Ссылка В(&Ссылка)";
        
    ПустаяНом = Справочники.Номенклатура.ПустаяСсылка();
    ТекУровень = 0;
    ТекМассив = Новый Массив;
    МассивРазныхНом = Новый Массив;
    Для Каждого ЭлементМассива ИЗ МассивНоменклатуры Цикл
        МассивРазныхНом.Добавить(ЭлементМассива);
        Если ЭлементМассива = ПустаяНом Тогда
            Продолжить;
        КонецЕсли;
        ТекМассив.Добавить(ЭлементМассива);        
    КонецЦикла;
    
    Для Каждого ЭлМас Из ТекМассив Цикл
        СтрТаб = ТаблицаГрупп.Добавить();
        СтрТаб.Группа = ЭлМас;
        СтрТаб.Номенклатура = ЭлМас;    
        СтрТаб.Уровень = ТекУровень;    
    КонецЦикла;
    ТекУровень = ТекУровень+1;
    
    Пока Истина Цикл
        ЗапросРод.УстановитьПараметр("Ссылка",ТекМассив);
        Выборка = ЗапросРод.Выполнить().Выбрать();
        ТекМассив = Новый Массив;
        ТекМассив.Очистить();
        СтруктураПоиска = Новый Структура("Группа",Неопределено);
        Пока Выборка.Следующий() Цикл
            Если Выборка.Родитель = ПустаяНом Тогда
                Продолжить;
            КонецЕсли;
            СтруктураПоиска.Группа = Выборка.Ссылка;
            СтрокиТабПоиска = ТаблицаГрупп.НайтиСтроки(СтруктураПоиска);
            Для Каждого СтрТабПоиска Из СтрокиТабПоиска Цикл
                СтрТаб = ТаблицаГрупп.Добавить();
                СтрТаб.Группа = Выборка.Родитель;
                СтрТаб.Номенклатура = СтрТабПоиска.Номенклатура;    
                СтрТаб.Уровень = ТекУровень;    
            КонецЦикла;
            Если ТекМассив.Найти(Выборка.Родитель) = Неопределено Тогда
                ТекМассив.Добавить(Выборка.Родитель);
            КонецЕсли;
        КонецЦикла;
        Для Каждого ЭлементМассива Из ТекМассив Цикл
            МассивРазныхНом.Добавить(ЭлементМассива);
        КонецЦикла;
        Если ТекМассив.Количество() = 0 Тогда
            Прервать;
        КонецЕсли;
        ТекУровень = ТекУровень+1;        
    КонецЦикла;
5 MaXpaT
 
18.08.14
14:53
(3) (4)
// я не знаю что дают "ИТОГИ ПО", пробовать/разбираться не хочу, изобрету свой квадратноколёсный велосипед

жесть конечно ...


мой запрос хотя бы для интереса в консольке запросов запустил, посмотрел, сделал бы выводы
6 alexei366
 
19.08.14
10:42
(5) Да посмотрел, ну вроде то, только он зачемто два раза элемент номенклатуры выводит но эт фиг с ним. Я просто думаю на уровне SQL запроса там наверно жесть твориться) хотя думаю да и фиг с ним на производительность наврятли повлияет.