Выходные записи, которые соответствуют условию, а также их родительские записи вплоть до корневой записи. Oracle SQL - PullRequest
0 голосов
/ 14 мая 2018

Есть такая таблица Oracle:

+----+-----+--------+
| ID | PID |  NAME  |
+----+-----+--------+
|  1 |     | testX  |
|  2 |     | test2  |
|  3 |   2 | test3  |
|  4 |   3 | testX  |
|  5 |   3 | test5  |
|  6 |   3 | test6  |
|  7 |   4 | test7  |
|  8 |   5 | test8  |
|  9 |   3 | test9  |
| 10 |   4 | test10 |
| 11 |   5 | testX  |
| 12 |   5 | test12 |
+----+-----+--------+

, где pid - идентификатор родительской записи.

Необходимо вывести все записи, которые соответствуют условию, а также их родительские записи вплоть до корневой записи. Такие родительские записи не должны дублироваться с теми родительскими записями, которые найдены на этапе поиска.

Например, при этом условии where name = 'testX' должен получить такой результат:

+----+-----+-------+
| ID | PID | NAME  |
+----+-----+-------+
|  1 |     | testX |
|  2 |     | test2 |
|  3 |   2 | test3 |
|  4 |   3 | testX |
|  5 |   3 | test5 |
| 11 |   5 | testX |
+----+-----+-------+

Как это сделать?

P.S. Oracle 11.2.0.4.0.

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Этот простой запрос должен помочь -

SELECT distinct id, pid, name FROM tab1
connect by prior pid = id
start with name = 'testX'
order by id
;

http://sqlfiddle.com/#!4/8da121/6/0

Вывод -

ID  PID     NAME
1   (null)  testX
2   (null)  test2
3   2       test3
4   3       testX
5   3       test5
11  5       testX
0 голосов
/ 14 мая 2018

Я уверен, что есть более элегантный способ сделать это, но это то, что я придумал.

Это предложение with для создания примера данных:

with testdata as
(select 1 ID,   null PID, 'testX' NAME from dual union all
select 2 ,      null,     'test2'      from dual union all
select 3 ,      2,        'test3'      from dual union all
select 4 ,      3,        'testX'      from dual union all
select 5 ,      3,        'test5'      from dual union all
select 6 ,      3,        'test6'      from dual union all
select 7 ,      4,        'test7'      from dual union all
select 8 ,      5,        'test8'      from dual union all
select 9 ,      3,        'test9'      from dual union all
select 10,      4,        'test10'     from dual union all
select 11,      5,        'testX'      from dual union all
select 12,      5,        'test12'     from dual)

Вот запрос:

select distinct id, pid, name
from(
select sys_connect_by_path(name,'/') path,
       id, pid, name
from testdata
connect by prior PID = ID)
where instr(path,'/testX') > 0
order by id

Я использовал SYS_CONNECT_BY_PATH, чтобы получить поле имени от всех родителей. Затем я только что проверил, что testX был одним из элементов в строке, используя instr.

Мои результаты:

ID      PID     NAME
1               testX
2               test2
3       2       test3
4       3       testX
5       3       test5
11      5       testX
...