Транзитивное замыкание запросом

07.11.12

Разработка - Запросы

В частности, показывается, как одним пакетным запросом найти ВСЕХ предков (потомков) в иерархическом справочнике. Аналогично можно определять входимость деталей в узлы и готовые изделия по их спецификациям, определять подмножества аналогичных запчастей по цепочке аналогов, решать другие подобные задачи. Приложен файл с примером отчета для замыкания иерархии произвольного справочника, позволяющий протестировать быстродействие запроса в разных условиях.

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

Наименование Файл Версия Размер
Отчет "Транзитивное замыкание иерархии"
.erf 9,13Kb
212
.erf 9,13Kb 212 Скачать

Несмотря на определенную «заумность» термина, транзитивное замыкание – это простое и часто встречающееся на практике понятие. Вот примеры:

  1. Если известно, что пункт А связан с пунктом Б, а пункт Б с пунктом В, то делая вывод о том, что пункт А в итоге связан и с пунктом В, мы «транзитивно замыкаем» отношение «связанность». 
  2. Если группа 1-1-1 входит в отдел 1-1, а тот, в свою очередь является частью департамента 1, то группа 1-1-1 также входит и в департамент 1 в результате «транзитивного замыкания» отношения «вхождение». 
  3. Если рядовой Иванов подчиняется лейтенанту Петрову, лейтенант Петров – капитану Сидорову, капитан Сидоров – майору Пронину, майор Пронин – полковнику Хитрову, а полковник Хитров – генералу Дурову, то рядовой Иванов, хотя и закончил мехмат, также подчиняется генералу Дурову в результате транзитивного замыкания отношения «подчинение».

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

Вопрос о том, как решать и можно ли вообще решить подобную задачу, встречается довольно часто. Можно упомянуть публикации "Получение родителя верхнего уровня с помощью СКД"[//infostart.ru/public/84547/], "Соединение в запросе, сравнение (В ИЕРАРХИИ)"[//infostart.ru/public/102086/], "Пример получения в запросе всех подразделений с учётом иерархии (неограниченный уровень вложенности подразделений)" [//infostart.ru/public/117349/], недавнее обсуждение на форуме "Запрос из справочника с выборкой подчиненных элементов" [http://forum.infostart.ru/forum26/topic72977/message781790/#message781790]. Решение, описываемое в статье, появилось в ходе обсуждения  "Реально написать хитрый запрос" [http://forum.infostart.ru/forum14/topic35991/message395140/#message395140], и было там же опубликовано [(103)], однако осталось почти незамеченным. Данная публикация восполняет этот пробел. 

Очевидная трудность решения данной задачи заключается в природе табличного представления отношений в реляционных СУБД. Допустим, отношения связанности (например) хранятся в таблице, которая имеет следующий вид:

Пункт ... связан с пунктом ...
1 2
2 3
3 4
... ...
99 100

Тогда, чтобы определить, что пункт 1 связан с пунктом 100, потребуется выполнить множество соединений, число которых, к тому же, будет зависеть от исходных данных.

Тем не менее, решение есть. Оно довольно простое, хотя и не очевидное. Решение опирается на кое-какую математику. Вот она:

Если А – матрица смежности графа исходного отношения, то ее элемент aij равен 1, если i связан с j и 0, если связи нет. Таким образом, ненулевые элементы матрицы А фактически отмечают существование в отношении путей длины 1, А2 (А в степени 2) – путей длины 2, А3 – путей длины 3 и так далее. Если Е – единичная матрица, то

 (А + Е)n = Аn + … + A3 + A2 + A + E.

Это специфическое биноминальное разложение представляет собой матрицу смежности графа, содержащего пути длины 0, 1, 2, 3, … , n. Здесь нет биноминальных коэффициентов, потому что операции умножения и сложения выполняются по правилам алгебры логики: 0+0=0, 0+1=1, 1+0=1, 1+1=1. Ну и поскольку в графе из N вершин нет путей длины больше N, то (A + E)N и будет матрицей смежности транзитивного замыкания исходного отношения.
Во всем, что говорилось до настоящего момента, ничего нового нет. Формулы выражают общеизвестный способ, когда мы по шагам накапливаем замыкание, добавляя на каждом шаге более длинные пути. То есть, в случае отношения иерархического подчинения, сначала находим и добавляем к итоговой таблице таблицу потомков уровня 1, потом уровня 2, потом уровня 3 и так далее.

Новое заключается в том, что:

  1. Замечено, что если M > N, где N – максимальная длина пути, то (A + E)N = (A + E)M. То есть, можно не бояться возведения в степень «с запасом», которая больше, чем максимальная длина пути (глубина иерархии). Результат от этого не изменится.
  2. Предлагается вычислять (A+E)M следующим быстрым и эффективным способом: (А+E)2 = (А+E)(А+E), (А+E)4 = (А+E)2 (А+E)2 , (А+E)8 = (А+E)4( А+E)4, (А+E)16 = (А+E)8( А+E)8 и так далее, пока степень не станет больше требуемой.

Если попытаться объяснить прием словами, без формул, то получится следующее:
На первом этапе объединяем (UNION) с исходной таблицей путей длины 1 таблицу путей длины 0 (каждый элемент связан с самим собой). Далее соединяем (JOIN) эту таблицу с собой, чтобы получить в результирующей таблице пути длины 0, 1 и 2. Снова соединяем полученную таблицу с собой и получаем в результирующей таблице пути длины 0, 1, 2, 3, 4. Уже в следующем соединении получим пути длины 0, 1, 2, 3, 4, 5, 6, 7, 8. Далее максимальная длина пути будет быстро расти и очень скоро преодолеет любой заданный предел.

При реализации на языке 1С, получается следующая достаточно компактная функция, возвращающая в качестве результата таблицу транзитивного замыкания. Функция приведена на примере отношения иерархии групп и элементов справочника. Эту функцию можно использовать как шаблон и для других отношений. Потребуется всего лишь заменить текст в переменной «Пролог».


Функция ТранзитивноеЗамыкание(ИмяСправочника, МаксимальнаяДлинаПути) Экспорт

    Пролог = "ВЫБРАТЬ Родитель НачалоДуги, Ссылка КонецДуги ПОМЕСТИТЬ ЗамыканияДлины1 ИЗ Справочник.Номенклатура

            | ГДЕ Родитель <> Значение(Справочник.Номенклатура.ПустаяСсылка)

            | ОБЪЕДИНИТЬ ВЫБРАТЬ Ссылка, Ссылка ИЗ Справочник.Номенклатура;"
;

    Рефрен = "ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины#2 ИЗ ЗамыканияДлины#1 КАК ПерваяДуга

            | ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины#1 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;

            | УНИЧТОЖИТЬ ЗамыканияДлины#1;"
;

    Эпилог = "ВЫБРАТЬ НачалоДуги Предок, КонецДуги Потомок ИЗ ЗамыканияДлины#2 ГДЕ НачалоДуги <> КонецДуги";

    Запрос = Новый Запрос(СтрЗаменить(Пролог, "Номенклатура", ИмяСправочника));

    МаксимальнаяДлинаЗамыканий = 1;

    Пока МаксимальнаяДлинаЗамыканий < МаксимальнаяДлинаПути Цикл

        Запрос.Текст = Запрос.Текст + СтрЗаменить(СтрЗаменить(Рефрен, "#1", Формат(МаксимальнаяДлинаЗамыканий, "ЧГ=0")), "#2", Формат(2 * МаксимальнаяДлинаЗамыканий, "ЧГ=0"));

        МаксимальнаяДлинаЗамыканий = 2 * МаксимальнаяДлинаЗамыканий

    КонецЦикла;

    Запрос.Текст = Запрос.Текст + СтрЗаменить(Эпилог, "#2", Формат(МаксимальнаяДлинаЗамыканий, "ЧГ=0"));

    Возврат Запрос.Выполнить().Выгрузить()

КонецФункции

В теле функции сначала собирается текст запроса. Он состоит из «пролога», который извлекает из базы данных исходное отношение, дополняет его путями нулевой длины и помещает результат во временную таблицу путей длины 1 и 0. Это единственная часть функции, которая зависит от структуры данных и типа исходного отношения. Далее следует «рефрен» - повторяемая часть запроса, в которой короткие пути соединяются в более длинные пути для новой временной таблицы, а также удаляется временная таблица, полученная на предыдущем шаге. Завершает текст запроса «эпилог», в котором извлекается итоговая временная таблица. После сборки полученный пакетный запрос единожды выполняется.

На первый взгляд может показаться, что текст запроса будет очень длинным. На самом деле, даже если справочник содержит миллион элементов в цепочке подчинения (мегаматрешка!), понадобится всего двадцать рефренов. Запрос будет в десятки (сотни?) раз короче некоторых запросов в ЗиУП. 

Второе замечание, которое можно предупредить, это то, что, возможно, потребуется отдельный запрос для определения количества элементов в справочнике, чтобы оценить максимальную длину пути (уровень подчинения). Ответом здесь будет то, что на практике почти всегда можно будет взять некоторое достаточно большое число, например 256 или 1000, исходя из характера задачи.

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

Ну и, наконец, для тех, кто заметил сходство математики предлагаемого метода и "Порождающего запроса" [//infostart.ru/public/90367/], могу добавить, что порождающий запрос появился именно вследствие данного решения.

P.S.: Если провести небольшой рефакторинг и перевести функцию на английский, она будет выглядеть компактней (всего 9 строк!)


function closure(name, N, M = 1) export

q = new query(strreplace("select parent a, ref b into r1 from catalog._ where parent <> value(catalog._.emptyref) union select ref, ref from catalog._;", "_", name));

while
M < N do

   
q.text = q.text + strreplace(strreplace("select distinct p1.a, p2.b into r#2 from r#1 as p1 join r#1 as p2 on p1.b = p2.a; drop r#1;", "#1", format(M, "NG=0")), "#2", format(2 * M, "NG=0"));

   
M = 2 * M

enddo;

q.text = q.text + strreplace("select a Предок, b Потомок from r#2 where a <> b", "#2", format(M, "NG=0"));

return
q.execute().unload()

endfunction

См. также

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

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

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

10000 руб.

02.09.2020    124928    682    389    

732

Пропорциональное распределение в запросе с использованием АвтоНомерЗаписи()

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

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    2242    andrey_sag    10    

28

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    6006    KawaNoNeko    23    

25

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    2149    2    Yashazz    0    

31

Запрос 1С copilot

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

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6637    31    mkalimulin    27    

51

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

Одной из интересных задач, стоящих в процессе разработки, была поддержка механизма представлений в ЗУП. Но не просто возможность исполнения запросов с ними. Основная проблема была в том, чтобы с ними было удобно работать, а именно: создавать, модифицировать и отлаживать. Кратко о том, что в итоге получилось...

14.12.2023    1880    vandalsvq    7    

29

Объектная модель запроса "Схема запроса" 2

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

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

06.12.2023    5625    user1923546    26    

46

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

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

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

11.10.2023    16593    skovpin_sa    14    

101
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
99. oldfornit 09.11.16 18:00 Сейчас в теме
(98) очень, очень плохо. База каааак сядет, каааак закряхтит...
+
100. Infector 201 09.11.16 18:05 Сейчас в теме
(99) Да база как раз таки переваривает, причем весьма большое количество словечек "родитель" (у меня справочник около 15 уровней)
Еще один плюс на мой взгляд - хорошая читаемость. Ну и интересный момент - во что разворачивает такой запрос платформа, когда отсылает его на СУБД и насколько он отличается от того варианта, когда мы напрямую записываем соединения на уровне 1С.
+
126. native-api 10.04.24 17:43 Сейчас в теме
(100) Линейная алгоритмическая сложность, как и при "тупых" соединениях. А у автора статьи -- логарифмическая. Он покрывает не до 15 уровней иерархии, а хоть до стольки, сколько есть элементов в справочнике, и даже тогда это работает быстро.

Платформа, насколько мне известно, разворачивает обращения через много точек в соответствующее число соединений. Как раз то, чего автор избегает.
+
101. treedo 124 24.08.17 14:47 Сейчас в теме
Интересно, а почему бы одинэс не регистрировать владельцов элемента для удобства работы с данными...
+
102. ildarovich 7861 24.08.17 16:59 Сейчас в теме
Это дополнительные затраты памяти на хранение вычисляемых связей и времени на вставку и удаление при изменении структуры. Поищите поиском "хранение иерархии в СУБД" - там есть и другие соображения.
native-api; +1
103. Xershi 1483 04.09.17 14:05 Сейчас в теме
Получил запрос:
ВЫБРАТЬ ВзаимодействиеОснование НачалоДуги, Ссылка КонецДуги ПОМЕСТИТЬ ЗамыканияДлины1 ИЗ Документ.ЭлектронноеПисьмоВходящее
 ГДЕ ВзаимодействиеОснование <> Значение(Документ.ЭлектронноеПисьмоВходящее.ПустаяСсылка)
     И Дата <= &ДатаУдаления
     И Важность <> Значение(Перечисление.ВариантыВажностиВзаимодействия.Высокая)
 ОБЪЕДИНИТЬ ВЫБРАТЬ Ссылка, Ссылка ИЗ Документ.ЭлектронноеПисьмоВходящее
 ГДЕ Дата <= &ДатаУдаления
     И Важность <> Значение(Перечисление.ВариантыВажностиВзаимодействия.Высокая);ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины2 ИЗ ЗамыканияДлины1 КАК ПерваяДуга
 ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины1 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
 УНИЧТОЖИТЬ ЗамыканияДлины1;ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины4 ИЗ ЗамыканияДлины2 КАК ПерваяДуга
 ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины2 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
 УНИЧТОЖИТЬ ЗамыканияДлины2;ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины8 ИЗ ЗамыканияДлины4 КАК ПерваяДуга
 ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины4 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
 УНИЧТОЖИТЬ ЗамыканияДлины4;ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины16 ИЗ ЗамыканияДлины8 КАК ПерваяДуга
 ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины8 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
 УНИЧТОЖИТЬ ЗамыканияДлины8;ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины32 ИЗ ЗамыканияДлины16 КАК ПерваяДуга
 ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины16 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
 УНИЧТОЖИТЬ ЗамыканияДлины16;ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины64 ИЗ ЗамыканияДлины32 КАК ПерваяДуга
 ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины32 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
 УНИЧТОЖИТЬ ЗамыканияДлины32;ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины128 ИЗ ЗамыканияДлины64 КАК ПерваяДуга
 ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины64 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
 УНИЧТОЖИТЬ ЗамыканияДлины64;ВЫБРАТЬ РАЗЛИЧНЫЕ ПерваяДуга.НачалоДуги, ВтораяДуга.КонецДуги ПОМЕСТИТЬ ЗамыканияДлины256 ИЗ ЗамыканияДлины128 КАК ПерваяДуга
 ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЗамыканияДлины128 КАК ВтораяДуга ПО ПерваяДуга.КонецДуги = ВтораяДуга.НачалоДуги;
 УНИЧТОЖИТЬ ЗамыканияДлины128;ВЫБРАТЬ НачалоДуги Предок, КонецДуги Потомок ИЗ ЗамыканияДлины256 ГДЕ НачалоДуги <> КонецДуги
Показать

Думаю над тем как из ТЗ сделать ДЗ. Т.к. мне нужны только записи верхнего уровня. Для задачи https://forum.infostart.ru/forum9/topic176912/
+
104. ildarovich 7861 05.09.17 10:40 Сейчас в теме
(103) Прочел обсуждение https://forum.infostart.ru/forum9/topic176912/ по диагонали. Не знаю, правильно ли я понял, что причиной взаимоблокировок является одновременное удаление письма и его основания (или, в общем, транзитивно-связанных писем).
Тогда рецепт - удалять в одной итерации один "слой" в несколько потоков?
Слой - это уровень. Возьмите концовку запроса из задачи про уровни и удаляйте, начиная с нулевого по порядку. Нулевой - это перед которым нет оснований.
+
105. Xershi 1483 05.09.17 21:32 Сейчас в теме
(104) я хотел взять вершки, для этого и хочу построить дерево. Если я вас правильно понял, то верхние уровни дерева будут, только те элементы у которых будет пустое значение "НачалоДуги"? Если так то мне этого достаточно будет!
+
106. ildarovich 7861 06.09.17 11:55 Сейчас в теме
(105) Чтобы взять вершки, дерево строить не обязательно. Условие НачалоДуги = пустое значение можно проверить до выполнения замыкания.
Смысл применять данный алгоритм есть только, если хотите разбить свое "дерево" (на самом деле это граф - то есть более общая структура) на слои - уровни.
Чтобы заранее запланировать последовательность удаления, не делая промежуточных запросов при определении нового верхнего слоя.
Кстати, при многопоточности этот промежуточные запросы вероятно могут приводить к блокировкам (?).
Поэтому смысл посчитать уровни заранее есть.
Но тут нужно еще предусмотреть возможное наличие циклов в связях документов.
+
107. Xershi 1483 06.09.17 12:56 Сейчас в теме
(106) так я так и не понял. Я правильно понял, что верхние узлы всегда будут там где пустое значение "НачалоДуги" или нет? В моем случае дерево строить и не надо, т.к. потоки вложенность отработают через поиск ссылок. Мне нужно только взять верхние узлы, потому что в моем алгоритме все связи линейные и иерархические.
+
108. ildarovich 7861 06.09.17 13:58 Сейчас в теме
(107) Вот это условие в вашем запросе
ВзаимодействиеОснование <> Значение(Документ.ЭлектронноеПисьмоВходящее.ПустаяСсылка)
приводит к тому, что пустого значения НачалоДуги в результирующей таблице вообще не будет.
Чтобы выбрать "вершки" из замыкания требуется вот такой запрос
ВЫБРАТЬ КонецДуги КАК Вершок ИЗ ЗамыканияДлины256 СГРУППИРОВАТЬ ПО КонецДуги ИМЕЮЩИЕ КОЛИЧЕСТВО(НачалоДуги) = 1

Но, кажется, тот же результат даст вот такой более гораздо простой запрос:
ВЫБРАТЬ Ссылка КАК Вершок ИЗ Документ.ЭлектронноеПисьмоВходящее
 ГДЕ (ВзаимодействиеОснование = Значение(Документ.ЭлектронноеПисьмоВходящее.ПустаяСсылка) ИЛИ (ВзаимодействиеОснование.Важность = Значение(Перечисление.ВариантыВажностиВзаимодействия.Высокая)))
     И Дата <= &ДатаУдаления
     И Важность <> Значение(Перечисление.ВариантыВажностиВзаимодействия.Высокая)
shu_vol; Артано; +2
110. kirinalex 15 27.12.18 09:57 Сейчас в теме
Отлично.
Для коллег, желающих понять матчасть рекомендую лекцию https://www.youtube.com/watch?v=FQ10fnuBB7A&t=2700s
Там очень доходчиво многое объясняется.
for_sale; +1
111. user1119853 02.01.19 20:30 Сейчас в теме
Прочитал статью, интересно, полезно для работы со всем справочником, можно ли адаптировать под один элемент справочника? (про получение родителя верхнего уровня)
+
112. Dovbenko_V_A 09.03.20 18:41 Сейчас в теме
Добрый день! Подскажите, в алгоритме транзитивного замыкания используется параметр "МаксимальнаяДлинаПути" (как я понял это максимальная степень вложенности элементов). Можно ли ее как-то вычислить до алгоритма простым способом(иначе получается опять же задача того же уровня)? Или достаточно использовать заранее большее значение (например 100500 :))
+
113. ildarovich 7861 10.03.20 00:21 Сейчас в теме
(112) Нужно взять достаточно большое значение. С запасом таким значением будет число элементов в графе, так как длина пути не может быть больше этого числа.
+
114. d_protos 09.04.20 20:52 Сейчас в теме
Добрый день, а есть решение вот для такого типа задач?

Есть таблица, описывающая подчиненность объектов. Каждый объект имеет свой тип, определяющий его уровень вложенности
Пусть объекты описываются так 1(A) где цифра это код объекта, а буква - уровень подчиненности. Путь уровней всего 4: A, B, C, D
Возьмем такую таблицу как пример
Емкость Вложение
1(А) 1(B)
1(A) 1©
1(B) 2©
2© 1(D)
2© 2(D)

Нужно получить вот такую таблицу
A B C D
1(A) 1(B) 2© 1(D)
1(A) 1(B) 2© 2(D)
1(A) - 1© -
Это возможно сделать запросом? С возможностью наложить фильтр на любом уровне
+
115. ildarovich 7861 10.04.20 13:58 Сейчас в теме
(114) Для этой конкретной задачи таких сложностей не нужно. Здесь нужно всего лишь сделать левое соединение таблицы второго уровня (Уровень = B) с таблицей первого уровня, в том же запросе опять левое соединение третьего уровня со вторым и четвертого с третьим. А затем вывести результат в виде конкатенации элементов таблиц первого, второго, третьего и четвертого уровня. С какими нужно фильтрами. То есть решением является простой запрос к четырем таблицам с тремя левыми соединениями.
Подход, приведенный в статье, нужен тогда, когда уровней существенно больше.
+
116. d_protos 10.04.20 18:27 Сейчас в теме
(115)
Для этой конкрет

Есть одна тонкость - связи могут быть между 3 и 1 уровнем напрямую.
Получается что нужно сделать все комбинации соединений
2-1
3-2
3-1
4-3
4-2
4-1
меня смущает скорость запроса при таком количестве соединений при больших объемах (около 0,5 млн записей в таблице)
+
117. ildarovich 7861 11.04.20 00:09 Сейчас в теме
(116) Вам виднее, потому что реальное содержание задачи вы не раскрыли. Опишите задачу поподробнее, если все же будет тормозить, чтобы можно было еще подумать. А для соединений при таком количестве записей индексы должны быть. Но, повторяю, решение из статьи не для этого случая, тем более, быстродействием оно не отличается.
+
118. brr 182 27.07.20 09:16 Сейчас в теме
мда, когда-то, когда выходила статья, слова "транзитивное замыкание" были для меня пустым звуком, что ты делаешь со мной alloy?
+
119. user1080864 04.02.21 17:07 Сейчас в теме
Добрый вечер.

Столкнулся с подобным решением на проекте.
Выбрасывает исключение - из за ограничения доступа к записям...
Вероятно в запросах стоило бы добавить РАЗРЕШЕННЫЕ для избежания подобных ошибок?
Не нарушит ли это логику запроса?

Или может лучше перед выполнением запроса - установить привилегированный режим?
+
120. ildarovich 7861 05.02.21 13:58 Сейчас в теме
(119) Конечно, логика не нарушится. РАЗРЕШЕННЫЕ добавляем по обстановке, как в рецептах - "соль и перец по вкусу" ))). Привилегированный режим с логикой запроса тоже никак не связан: если исходные данные смогут быть выбраны - запрос отработает.
+
121. пользователь 15.02.21 17:42
Сообщение было скрыто модератором.
...
122. Ambakollajder 01.07.21 12:44 Сейчас в теме
(120) Только прочитал статью, в голове еще не все встало на свои полки, если мне нужно получить все транзитивные замыкания одного конкретного элемента справочника, как можно оптимизировать запрос, как я понял все равно придется перебирать все элементы справочника на каждом шаге увеличения длинны пути?
+
123. emakei 01.06.22 22:08 Сейчас в теме
Я не смотрел все комментарии, но почему просто не использовать стандартную возможность построения и проверки иерархии в СКД?
+
124. truba 12.05.23 09:30 Сейчас в теме
125. FC187GEB 18.10.23 17:26 Сейчас в теме
Спасибо, очень помогло. Необходимо было развернуть справочник подразделений и вывести в строку для каждого сотрудника всю иерархию начиная с прародителя по уровням. С этой функцией и составить запрос получилось быстро, и работает быстро.
+
127. native-api 10.04.24 20:34 Сейчас в теме
Доступен ли код под свободной лицензией?
По пользовательскому соглашению Инфостарта, по умолчанию он предоставляется только для ознакомления.
+
Оставьте свое сообщение