powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Проверка на циклы в иерархической таблице(Головоломка)
25 сообщений из 61, страница 1 из 3
Проверка на циклы в иерархической таблице(Головоломка)
    #39998584
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Навеяно другой темой, про constraints и проверку данных на вшивость.

Задана таблица EMPLOYEES с полями employee_id и manager_id типа integer.
Таблица описывает строгую древовидную иерархию, с одним гендиректором наверху.

Как в SQL (или в PL/SQL, чтоб легче) подтвердить правильность древовидной структуры?
Критерии правильности древовидности довольно очевидна но на всякий случай в вики есть определение:

https://ru.wikipedia.org/wiki/Дерево_(структура_данных)
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998585
Фотография Relic Hunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
select count(*) from employees where manager_id is null
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998586
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
НеофитSQL,

На форуме ужн многократно обсуждалось, решения элементарные, а на современных версиях ещё легче. Но ты пиши, посмотрим...
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998589
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Relic Hunter
Код: plsql
1.
select count(*) from employees where manager_id is null



Лаконично. Похоже, что производится подсчет гендиректоров, из предположения что гендиректор помечен null.
Это не единственный способ отметить гендиректора, но вполне рабочий. Для этого manager_id придется сделать nullable, расслабив одно из ограничений.

Этот тест отловит таблицы где нет гендиректоров, или более одного гендиректора. Некоторые вещи он пропустит.

Код: plaintext
1.
2.
3.
4.
5.
6.
Контрпример: следующие таблицы обе вернут (1), но вторая из них не отвечает определению дерева.

EMPLOYEES_GOOD       EMPLOYEES_BAD
emp_id  mgr_id       emp_id  mgr_id
===============================================
  5       0           5       0
  8       5           8       8

У меня пока тоже не получается записать эту задачу на SQL, т.к. мое решение полагается на цикл, а с циклами в SQL туго.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998623
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL,

проверить что все "узлы" employee_id в дереве и нет циклов?

ps
connect by, with ...

....
stax
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998738
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL
Некоторые вещи он пропустит.

Код: plaintext
1.
2.
3.
4.
5.
6.
Контрпример: следующие таблицы обе вернут (1), но вторая из них не отвечает определению дерева.

EMPLOYEES_GOOD       EMPLOYEES_BAD
emp_id  mgr_id       emp_id  mgr_id
===============================================
  5       0           5       0
  8       5           8       8


Пропустит, но не это. Это предотвращается а не проверяется. Например через FBI на EMPLOYEES(1 / (EMPNO - MGR)) или через calculated column X = EMPNO - MGR плюс check constraint CANT_SELFREPORT на X != 0.

SY.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998746
Фотография кит северных морей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY
НеофитSQL
Некоторые вещи он пропустит.

Код: plaintext
1.
2.
3.
4.
5.
6.
Контрпример: следующие таблицы обе вернут (1), но вторая из них не отвечает определению дерева.

EMPLOYEES_GOOD       EMPLOYEES_BAD
emp_id  mgr_id       emp_id  mgr_id
===============================================
  5       0           5       0
  8       5           8       8


Пропустит, но не это. Это предотвращается а не проверяется. Например через FBI на EMPLOYEES(1 / (EMPNO - MGR)) или через calculated column X = EMPNO - MGR плюс check constraint CANT_SELFREPORT на X != 0.

SY.
а просто чек на empno != mgr?
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998758
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Мне приятно, что есть желающие размять мозги и возможно, блеснуть кодом.

Действительно, можно ввести проверку на eid != mid (давайте сократим эти поля employee_id и manager_id).
Такая проверка исключит тривиальные циклы. Но пропустит более длинные.

Контрпример: цикл из двух, не ловится вышеописанной проверкой.

Код: plaintext
1.
2.
3.
4.
5.
EMPLOYEES_GOOD       EMPLOYEES_BAD
emp_id  mgr_id       emp_id  mgr_id
===============================================
  5       0           5       0
  8       5           8       3
  3       5           3       8

В этом контрпримере, в "хорошей" таблице строчки 2-3 подчинены гендиректору, а в "плохой" таблице - друг другу (цикл).
Цикл может быть из трех и более - нужно ловить все.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998761
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кит северных морей
а просто чек на empno != mgr?


Brain fart

SY.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998767
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL


В этом контрпримере, в "хорошей" таблице строчки 2-3 подчинены гендиректору, а в "плохой" таблице - друг другу (цикл).
Цикл может быть из трех и более - нужно ловить все.


А это без сериализации не предотвращается а проверить можно только полным проходом по дереву.

SY.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998776
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Stax
НеофитSQL,

проверить что все "узлы" employee_id в дереве и нет циклов?

ps
connect by, with ...

....
stax


Чувствуется человек с опытом работы - первым делом уточнил условия задачи.

Дополнение к первому сообщению, более конкретные условия задачи:
1) гендиректор обозначается manager_id (mid) = null
2) пустая таблица не считается деревом
3) таблица из одного и более элементов может быть деревом (только гендиректор - считать деревом)
3) в дереве ровно один ген директор
4) циклы в графе запрещены - у дерева не бывает циклов
5) каждый сотрудник должен быть напрямик или через других подчинен гендиректору
6) результат функции или запроса должен говорить "дерево" или "не дерево" (true/false, 1/0, на усмотрение)
7) код должен отрабатывать за конечное время, быстрее - лучше

Я заметил что в коммерческих решениях зачастую вершина дерева помечается как mid=eid, а не как mid=null.
Думаю, что это делается с целью усиления constraints, тогда mid можно определить non-nullable внешний ключ.
Если к этому добавить запрет на mid=eid для INSERT, будет невозможно испортить дерево при добавлении сотрудников.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998780
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL

Цикл может быть из трех и более - нужно ловить все.

connect by нельзя пльзоваться?

....
stax
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998791
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тривиально: пройтись по всем записям, выстраивая иерархию от подчиненного к менеджеру.
Обработать exception "connect-by loop in user data" либо проконтролировать соответствующий флаг.
Отобрать листья.
Сгруппировать листья и убедиться, что результатом группировки является единственная запись и эта запись соответствует корню иерархии.
Фсьо.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998810
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Можно пользоваться connect by, и любыми другими встроенными средствами Оракл.

Если там есть встроенная команда проверки всего дерева, то это было бы самым правильным решением.

Кстати, я не знал про существование connect by до этого момента, сейчас читаю как эта конструкция обрабатывает циклы.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998814
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемый, уже несколько дней наблюдаю за Вашим творчеством.
Не скрою,увлекательно.
Продолжайте пожалуйста.
Только огромная просьба: пожалуйста, ни в коем случае не изучайте выбранный технологический стек, не читайте документацию - от этого Ваши сообщения могут существенно потерять в лулзах.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998824
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL
Если там есть встроенная команда проверки всего дерева,

В множестве типа "куча" нет деревьев, но можно хранить записи, имеющие логические ссылки на соседние. На этом всё.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998828
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymous
Тривиально: пройтись по всем записям, выстраивая иерархию от подчиненного к менеджеру.
Обработать exception "connect-by loop in user data" либо проконтролировать соответствующий флаг.
Отобрать листья.
Сгруппировать листья и убедиться, что результатом группировки является единственная запись и эта запись соответствует корню иерархии.
Фсьо.


Это звучит как решение. Вряд ли я такое сегодня смогу написать на SQL.

А вот connect-by/noloop - очень полезная штука, я о ней до этого не знал.
С этим оператором задача упрощается в разы.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998834
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL

С этим оператором задача упрощается в разы.


Не упрощается. В многопользовательском режиме (что есть стандарт) такая проверка (CONNECT BY) ничего не гарантирует. Без сериализации тут не обойтись.

SY.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998837
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQLКак в SQL (или в PL/SQL, чтоб легче) подтвердить правильность древовидной структуры?

Составной ключ id+уровень иерархии, соответствующий FK и сверху chеck, проверяющий уровень
иерархии менеджера выше, чем у работника.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998838
Фотография Sayan Malakshinov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Модератор форума
SY,

Да что ж вы делаете-то... Остановитесь! Сейчас ещё одна же тема появится, теперь про уровни изоляции транзакций и мини-откаты... Прямо галопом по европам...
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998841
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov

НеофитSQLКак в SQL (или в PL/SQL, чтоб легче) подтвердить правильность древовидной структуры?

Составной ключ id+уровень иерархии, соответствующий FK и сверху chеck, проверяющий уровень
иерархии менеджера выше, чем у работника.


Идея понятна, но уровень иерархии не определен для циклов.
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998844
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQLуровень иерархии не определен для циклов.

В дереве не существует циклов.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998853
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SY

В многопользовательском режиме (что есть стандарт) такая проверка (CONNECT BY) ничего не гарантирует. Без сериализации тут не обойтись.
SY.


В многопользовательском режиме CONNECT BY исполняется по-другому, и ему нельзя доверять?
Я написал следующее условие, которое true если дерево, и false если не дерево.
Оно использует connect by, оно сломается и даст неверные данные в многопользовательском режиме?
Или вы говорите о ситуации, когда таблица меняется во время исполнения проверок?
Если так, то добавим условие что таблицу считать статической на время проверки (напр., копия)

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
(select  count(*)
   from  EMPLOYEES
   start with mid is null
 connect by
 nocycle
   prior eid = mid)
 =(select count(*) from EMPLOYEES) 
and 
(select count(*) from EMPLOYEES where mid is null) = 1
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998857
НеофитSQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov

НеофитSQLуровень иерархии не определен для циклов.

В дереве не существует циклов.


Действительно. У дерева нет циклов, и ровно один корень.
Условие этой головоломки - определить представляет ли таблица правильное дерево.

Ваше предложенное решение начинается с "предположим, что это правильное дерево, где определен уровень иерархии.." :)
...
Рейтинг: 0 / 0
Проверка на циклы в иерархической таблице(Головоломка)
    #39998860
dmdmdm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НеофитSQL

В многопользовательском режиме CONNECT BY исполняется по-другому, и ему нельзя доверять?


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

и не выдумывать фантастических ситуаций

таблицу считать статической на время проверки (напр., копия)
...
Рейтинг: 0 / 0
25 сообщений из 61, страница 1 из 3
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Проверка на циклы в иерархической таблице(Головоломка)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]