Выбор всех строк-потомков из таблицы Oracle, представляющей древовидную структуру

У меня есть таблица MYTYPE в Oracle 10g, представляющая древовидную структуру, которая выглядит примерно так:

ID | PARENTID | DETAIL

Я хотел бы выбрать все строки в MYTYPE, которые являются потомками определенного идентификатора, чтобы я мог создавать запросы в другом месте, например:

SELECT * 
  FROM MYDETAIL 
 WHERE MYTYPEID IN [all MYTYPE which are descendants of some ID];

Каков экономичный способ построения набора потомков, предпочтительно без использования PL/SQL?


person ckpwong    schedule 17.01.2011    source источник
comment
плохой тон задавать вопросы и не выбирать правильный ответ или предоставлять дополнительную информацию о том, какая помощь вам все еще нужна.   -  person orangepips    schedule 28.01.2011


Ответы (4)


Oracle не поддерживал иерархический синтаксис ANSI с использованием рекурсивного факторинга подзапросов (CTE в синтаксисе SQL Server) до версии 11g R2, поэтому вы должны использовать собственный синтаксис Oracle CONNECT BY (поддерживается, начиная с v2):

   SELECT t.*
      FROM MYTABLE t
START WITH t.parentid = ?
CONNECT BY PRIOR t.id = t.parentid

Замените вопросительный знак родителем, на основе которого вы хотите найти иерархические данные.

Справка:

person OMG Ponies    schedule 17.01.2011

Управление иерархическими данными с использованием ID,ParentID столбцов в СУБД известно как модель списка смежности. Хотя очень легко реализовать и поддерживать (т. е. вставлять, обновлять, удалять), определение родословной (т. е. предков и потомков) обходится дорого. Как уже писали другие ответы, Oracle CONNECT BY будет работать, но это дорогостоящая операция. Возможно, вам будет лучше представлять свои данные по-другому.

В вашем случае самым простым решением может стать добавление так называемой иерархии. Соедините таблицу со своей схемой и добавьте столбец LEVEL в исходную таблицу. В таблице есть столбцы ID,DescendantID, при этом выбор по ID дает все записи потомков, а выбор по DescentantID дает все записи предков. LEVEL необходимо в базовой таблице для упорядочения записей. Таким образом, вы делаете компромисс между дорогими обновлениями и дешевым чтением, что и подразумевает ваш вопрос.

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

person orangepips    schedule 18.01.2011

Oracle может выполнять рекурсивные запросы. Попробуйте заглянуть в start with ... connect by, что-то вроде этого:

Select *
from MYDETAIL
Starting with PARENTID= 1 --or whatever the root ID is
connect by PARENTID = prior ID

http://psoug.org/reference/connectby.html

person FrustratedWithFormsDesigner    schedule 17.01.2011

Вот подробности о функциях «подключения» в оракуле. http://psoug.org/reference/connectby.html

person Abhishek Maurya    schedule 01.02.2013