Выбор идентификатора листа + корневого имени из таблицы в Oracle - PullRequest
2 голосов
/ 23 августа 2010

У меня есть таблица с самоссылкой, с id, parentid (ссылочный id), именем, упорядоченным в виде столбцов.

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

Данные могут иметь неограниченные уровни, а у братьев и сестер есть порядок (назначаемый столбцом «порядок»). «Первый листовой узел» означает первого ребенка первого ребенка, первого ребенка (и т. Д.).

Данные выглядят примерно так: братья и сестры упорядочены по порядку:

A
--a

---- стр.1
---- б2
---- В.3
B

---- с.1
---- с.2
-D,
C
--e
---- д.1
------ e.1.1

Я хочу иметь возможность составить карту следующим образом:
имя А, идентификатор
имя B, идентификатор c.1
имя C, идентификатор e.1.1

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

select id,  
       connect_by_root name name 
  from table 
 where connect_by_isleaf = 1 
   and ((level = 2 and ordering = 1) 
    or (level > 2 and ordering = 1 and prior ordering = 1)) 
start with parentid is null 
connect by prior id = parentid;

Можно ли как-нибудь переписать sql, чтобы сделать его неограниченным?

1 Ответ

2 голосов
/ 23 августа 2010

Я бы использовал подзапрос:

SQL> SELECT root_name, MIN(leaf_name) first_leaf
  2    FROM (SELECT id, connect_by_root(r.NAME) root_name, r.NAME leaf_name
  3             FROM recurse r
  4            WHERE connect_by_isleaf = 1
  5            START WITH parentid IS NULL
  6           CONNECT BY PRIOR id = parentid)
  7   GROUP BY root_name;

ROOT_NAME  FIRST_LEAF
---------- ----------
A          a
B          c.1
C          e.1.1

Это даст вам первый лист (упорядоченный по имени листа) для каждого корня.


Обновление

Это скрипт, который я использовал для генерации ваших данных:

CREATE TABLE recurse (
   ID NUMBER PRIMARY KEY, 
   name VARCHAR2(10), 
   parentid NUMBER REFERENCES recurse (ID));

INSERT INTO recurse VALUES (1, 'A', '');
INSERT INTO recurse VALUES (3, 'b', 1);
INSERT INTO recurse VALUES (4, 'b.1', 3);
INSERT INTO recurse VALUES (5, 'b.2', 3);
INSERT INTO recurse VALUES (6, 'b.3', 3);
INSERT INTO recurse VALUES (7, 'B', '');
INSERT INTO recurse VALUES (8, 'c', 7);
INSERT INTO recurse VALUES (9, 'c.1', 8);
INSERT INTO recurse VALUES (10, 'c.2', 8);
INSERT INTO recurse VALUES (11, 'd', 7);
INSERT INTO recurse VALUES (12, 'C', '');
INSERT INTO recurse VALUES (13, 'e', 12);
INSERT INTO recurse VALUES (14, 'e.2', 13);
INSERT INTO recurse VALUES (15, 'e.1', 13);
INSERT INTO recurse VALUES (16, 'a', 1);
INSERT INTO recurse VALUES (20, 'e.1.1', 15);

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

Теперь предположим, что вы хотите сделать заказ по идентификатору (или по любому другому столбцу, который не имеет значения), вы хотите использовать аналитику, например:

SQL> SELECT DISTINCT root_name,
  2         first_value(leaf_name)
  3            over(PARTITION BY root_name ORDER BY ID) AS first_leaf_name
  4    FROM (SELECT id, connect_by_root(r.NAME) root_name, r.NAME leaf_name
  5             FROM recurse r
  6            WHERE connect_by_isleaf = 1
  7            START WITH parentid IS NULL
  8           CONNECT BY PRIOR id = parentid)
  9   ORDER BY root_name;

ROOT_NAME  FIRST_LEAF_NAME
---------- ---------------
A          b.1
B          c.1
C          e.2
...