Имя: Пароль:
1C
1С v8
Запрос к справочнику: элемент и все его группы
0 Asmody
 
22.04.19
12:34
Телезритель Asmody из Москвы задает вопрос знатокам:
Уважаемые знатоки! Допустим, у меня есть иерархический справочник (например, Номенклатура), с произвольным уровнем иерархии. Как мне запросом получить элементы справочника и все содержащие его группы?
Показываю на примере:



Группа1
|_Группа11
| |_Группа111
|   |_Элемент1
|_Группа12
  |_Элемент2



в результате:


Элемент1 | Группа1
Элемент1 | Группа11
Элемент1 | Группа111
Элемент2 | Группа1
Элемент2 | Группа12

1 Cyberhawk
 
22.04.19
12:35
В 1С иерархия элементов и групп допускает только одного владельца
2 Cyberhawk
 
22.04.19
12:35
("родителя")
3 Asmody
 
22.04.19
12:36
На самом деле, вопрос "со звездочкой".
Мне нужны не все группы, а подходящие по определенному условию.
Но это можно решить отбором на результат запроса из (0)
4 1Сергей
 
22.04.19
12:38
Можно наклепать там двадцать левых соединений, но потом хоп и попадутся элементы на 22 уровне и пипец
5 fisher
 
22.04.19
12:40
Ответ "со звездочкой": http://catalog.mista.ru/public/158512/
Эффективно, если нужно по всему справочнику.
6 Asmody
 
22.04.19
12:42
(5) Да, этот способ я знаю. Там текст запроса программно формируется. Меня это не совсем устраивает.
7 Вафель
 
22.04.19
12:43
(6) тогда никак
8 Вафель
 
22.04.19
12:44
ну или храни иерархию отдельно
9 Nuobu
 
22.04.19
12:46
В ИЕРАРХИИ наоборот?
10 Asmody
 
22.04.19
12:47
(9) Да. Если бы можно было использовать В ИЕРАРХИИ() в соединении таблиц.
11 lodger
 
22.04.19
12:47
можно запрос и постобработку?
в конце запроса пишем
    |ИТОГИ ПО
    |    Родитель ИЕРАРХИЯ";

    РезультатЗапроса = Запрос.Выполнить();
    ОсновнаяВыборка = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
    Пока ОсновнаяВыборка.Следующий() Цикл
// работаем с ОсновнаяВыборка.Родитель

        ВыборкаДетальныеЗаписи = ОсновнаяВыборка.Выбрать();
        
        Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
// работаем с детзаписями
        КонецЦикла;
        
    КонецЦикла;
12 fisher
 
22.04.19
12:48
(6) Программное формирование там только для оптимизации результирующего запроса под конкретный максимальный уровень вложенности. Фишка этого метода - в возможности покрытия очень большого уровня вложенности за небольшое количество шагов (нелинейная зависимость). То есть ты можешь просто написать готовый запрос с небольшим количеством этапов (не программно), который будет покрывать любую разумную глубину вложенности (сотню, скажем).
13 xXeNoNx
 
22.04.19
12:50
>>Как мне запросом получить элементы справочника и все содержащие его группы?
... содержащие его - в смысле?

Иерархию можно записать в виде таблицы
ВЫБРАТЬ
Ссылка(представление),
Родитель(представление)
ЭтоГруппа
ИЗ
Справочник.Номенклатура
14 xXeNoNx
 
22.04.19
12:54
Вопрос аналогичен групповым скидкам?
15 1Сергей
 
22.04.19
12:56
ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    НоменклатураРодитель.Ссылка КАК Родитель
ИЗ
    Справочник.Номенклатура КАК Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК НоменклатураРодитель
        ПО (Номенклатура.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
        ИЛИ (Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель.Родитель = НоменклатураРодитель.Ссылка)
ГДЕ
    НЕ НоменклатураРодитель.Ссылка ЕСТЬ NULL
16 Asmody
 
22.04.19
13:02
Тогда попробую задачу сначала в упрощенном виде описать:
Мне нужно получить данные из регистра Продажи по номенклатуре. И эти данные должны быть свернуты по группам. Но не по всем группам в иерархии, а только по тем, которые имеют некоторый признак (для простоты считаем, что это булевый реквизит у группы НужнаяГруппа). "Нужные группы" не обязательно верхние. Кроме того, "нужные группы" могут быть вложены, но не подряд, а, например, через уровень.
Соответственно, образуется такая "псевдоиерархия".
Можно, конечно, запихнуть всё это в СКД, и постобработкой выводить только нужные строки, но это как-то неаккуратненько.
17 fisher
 
22.04.19
13:07
(16) Напрашивается настройка формирования СКД по собственной иерархии, которую получать отдельным запросом. Но вычисление этой иерархии в запросе с "пропуском" уровней - это ИМХО будет уже удаление гландов ректально. Я бы попробовал подсунуть требуемую иерархию групп в СКД в качестве объекта ТЗ.
18 fisher
 
22.04.19
13:08
Хотя, если подумать, то может и в запросе получится не так сложно, как мне сначала показалось.
19 _Дайвер_
 
22.04.19
13:25
Получение всех родителей элемента
В языке запросов не предусмотрено специальных средств для получения всех родителей элемента. Для выполнения задачи можно воспользоваться иерархическими итогами, однако получение иерархических итогов оптимизировано для построения итогов большого количества записей, и не вполне эффективно для получения родителей одного элемента. Для более эффективного получения всех родительских записей элемента, рекомендуется перебирать в цикле его родителей небольшими порциями. Пример:

Пример:

ТекущийЭлементНоменклатуры = ЭлементНоменклатура;

Запрос = Новый Запрос("ВЫБРАТЬ
                      | Номенклатура.Родитель,
                      | Номенклатура.Родитель.Родитель,
                      | Номенклатура.Родитель.Родитель.Родитель,
                      | Номенклатура.Родитель.Родитель.Родитель.Родитель,
                      | Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель
                      |ИЗ
                      | Справочник.Номенклатура КАК Номенклатура
                      |
                      |ГДЕ
                      | Номенклатура.Ссылка = &ТекущийЭлементНоменклатуры";

Пока Истина Цикл
    Запрос.УстановитьПараметр("ТекущийЭлементНоменклатуры", ТекущийЭлементНоменклатуры);
    Результат = Запрос.Выполнить();
    Если Результат.Пустой() Тогда
        Прервать;
    КонецЕсли;
    Выборка = Результат.Выбрать();
    Выборка.Следующий();
    Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
        ТекущийЭлементНоменклатуры = Выборка[НомерКолонки];
        Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда
            Прервать;
        Иначе
            Сообщить(ТекущийЭлементНоменклатуры);
        КонецЕсли;
    КонецЦикла;

    Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда
        Прервать;
    КонецЕсли;
КонецЦикла;

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

Если число уровней в справочнике ограничено и невелико, то возможно получение всех родителей одним запросом без цикла.
20 Ботаник Гарден Меран
 
22.04.19
13:29
Нормально запросом как в (5)
Количество уровней растет как степени двойки.
7 подзапросов и количество уровней 128 будет.
Есть такие маньяки, располагающие номенклатуру в сотом уровне вложенности?
21 fisher
 
22.04.19
14:10
(20) Полная постановка задачи - в (16)
22 Ботаник Гарден Меран
 
22.04.19
14:24
(21)
Это надо за ТС всё сделать?
Тогда ему сюда: https://1cers.ru/pro/index.php
23 Сияющий в темноте
 
22.04.19
15:20
А если просто запрос элементов,а в итогах иерархия-он же сам ее построит,останется только выбрать и положить в таблицу.
24 Сияющий в темноте
 
22.04.19
15:25
а по сути,выбираем в таблицу все элементы и группы и их непосредственные родители.
делаем индекс по элементам.
добавляем колонку номер строки с группой.

далее,из выборки необходимых элементов берем элемент и ищем его в созданной таблице,если номер строки группы задан,то переходим на нее и пишем группу,если нет,то или группа пустая и мы все нашли,или ищем в таблице группу и проставляем ей номер,чтобы в след.раз не искать,и так далее ...
25 Asmody
 
22.04.19
15:29
Пока сделал через 5 раз ОБЪЕДИНИТЬ ВСЕ хвостом из Родитель.Родитель.Родитель...
26 Жан Пердежон
 
22.04.19
15:39
(25) лучше б уж через доп.свойство/реквизит, в аналитических отчетах на иерархию опираться - в любом случае костыль будет
27 Anarki
 
22.04.19
17:10
(16)Была задача один в один почти, и делал через транзитивное замыкание по статье из(5)
Пользователь не знает, чего он хочет, пока не увидит то, что он получил. Эдвард Йодан