Oracle подключается несколькими родителями

Я столкнулся с проблемой, используя connect by.

У меня есть запрос, с помощью которого я получаю несколько столбцов, включая эти три:

  • ID
  • идентификатор родителя
  • идентификатор объекта

Теперь для одних и тех же ID и parentID существует несколько связанных объектов, например.

ID ParentID ObjectID
1 0 112
1 0 113
2 0 111
2 0 112
3 1 111
4 1 112

Я пытаюсь использовать connect by, но не могу получить результат в правильной иерархии. Мне нужно, как показано ниже. Возьмите комбинацию ID-parentID, отобразите все строки с этим ID-parentID, а затем все дочерние элементы этого ID, т.е. чьи parentID=ID

ID ParentID ObjectID
1 0 112
1 0 113
3 1 111
4 1 112
2 0 111
2 0 112

select ID,parent_id, object_id from table start with parent_id=0 
connect by prior id=parent_id order by id,parent_id

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


person Riddhi Shah    schedule 21.06.2012    source источник
comment
Ввод 0? и вы хотите первые два уровня Чайлдс? Я не понимаю, чего вы пытаетесь достичь.   -  person Florin Ghita    schedule 21.06.2012
comment
@FlorinGhita Я хочу получить данные в иерархическом формате. Но дело в том, что вместе с идентификатором и родительским идентификатором у меня может быть несколько идентификаторов объекта. Как использовать connect by в этом сценарии.   -  person Riddhi Shah    schedule 21.06.2012
comment
Я думаю, вам нужен вложенный запрос. Внутренний запрос даст комбинацию идентификатора и родительского идентификатора, а внешний запрос извлечет все связанные записи.   -  person Padmarag    schedule 21.06.2012
comment
@padmarag Я использую вложенный запрос. Внутренний запрос приведет к данным из трех столбцов, как показано выше. Но после этого я не могу применить connectby для получения точной иерархической структуры.   -  person Riddhi Shah    schedule 21.06.2012


Ответы (3)


Ну, ваша проблема, похоже, в том, что вы используете ненормализованный дизайн таблицы. Если данный ID всегда имеет одно и то же ParentID, это отношение не должно указываться отдельно во всех этих строках.

Лучше было бы иметь одну таблицу, показывающую отношения между родителем и потомком, с ID в качестве первичного ключа, и вторую таблицу, показывающую сопоставления ID с ObjectID, где, я полагаю, оба столбца вместе составляют первичный ключ. Затем вы примените свой иерархический запрос к первой таблице и соедините его результаты с другой таблицей, чтобы получить соответствующие объекты для каждой строки.

Вы можете эмулировать это с вашей текущей структурой таблицы...

with parent_child as (select distinct id, parent_id from table),
     tree as (select id, parent_id from parent_child
               start with parent_id = 0
               connect by prior id = parent_id )
select id, table.parent_id, table.object_id
  from tree join table using (id)
person Dave Costa    schedule 21.06.2012
comment
Но вы теряете порядок, и я предполагаю, что это то, о чем действительно заботится ОП; ваш запрос эквивалентен (с данными OP) только select * from table. - person Alex Poole; 21.06.2012
comment
Однако вы можете включить rownum as rn в выбор из parent_child, а затем, наконец, order by rn, table.object_id. Что избавило меня от необходимости публиковать аналогичный ответ, над которым я работал. - person Alex Poole; 21.06.2012
comment
@DaveCosta У меня такой же дизайн стола, как вы упомянули. Первая таблица с ID и ParentID. Вторая таблица с ID и ObjectID. Я уже пробовал сначала получить иерархический запрос из первой таблицы, а затем объединить его со второй таблицей. Но при таком подходе терялась иерархическая последовательность. Он не возвращал значения в соответствии с иерархией. Поэтому я поднял этот вопрос, чтобы применить иерархию к объединенным данным. - person Riddhi Shah; 22.06.2012
comment
@AlexPoole - когда я попробовал это, как показано выше, оно вышло в том порядке, в котором ОП указал, что он искал - person Dave Costa; 22.06.2012
comment
@RS Ну, я ответил на опубликованную вами информацию, которая ничего из этого не указывает. Запрос, который вы показываете в вопросе, имеет предложение ORDER BY, которое явно сортирует строки по ID - зачем вы это делаете, если это не тот порядок, который вам нужен? - person Dave Costa; 22.06.2012

Вот скрипт, который работает. Не идеально, но будет работать -

select * from (select distinct test.id,
                    parent_id,
                    object_id,
                    connect_by_root test.id root
      from test
     start with test.parent_id = 0
    connect by prior test.id = parent_id)
order by root,id
person Padmarag    schedule 21.06.2012

Прежде всего Спасибо всем, кто пытался мне помочь.

Наконец, я изменил свой подход, так как применение предложения иерархии CONNECT BY к внутреннему запросу с несколькими соединениями не работало для меня.

Я принял следующий подход

  1. Получите иерархические данные из первой таблицы, т.е. таблицы с ID-ParentID. Выберите Query table1 с помощью CONNECT BY. Он даст идентификатор в правильной последовательности. Присоединитесь к полученному списку идентификаторов.

  2. Передайте указанный выше идентификатор в виде строки, разделенной запятыми, в предложении выбора запроса IN во вторую таблицу с ID-ObjectID.

выберите * из таблицы2, где ID в порядке (над присоединенной строкой идентификатора) по instr('над присоединенной строкой идентификатора',ID);

ORDER BY INSTR сотворил чудо. Это даст мне результат, упорядоченный по данным IN Clause, а строка IN Clause подготовлена ​​​​с использованием иерархического запроса. Следовательно, это, очевидно, будет последовательно.

Еще раз Спасибо всем за помощь!

Примечание. Приведенный выше подход имеет одно ограничение: идентификатор передается в виде строки, разделенной запятыми, в пункте IN. Предложение IN имеет ограничение на количество символов внутри. Думаю 1000 символов. Не уверен. Но, как я уверен по данным первой таблицы, это будет не так много, чтобы пересечь лимит в 1000 символов. Поэтому я выбрал вышеуказанный подход.

person Riddhi Shah    schedule 22.06.2012