Рекурсивный запрос в Oracle - длина цепочки - PullRequest
0 голосов
/ 28 января 2020

У меня есть таблица с некоторыми сообщениями. Сообщение имеет поля: post_id (key) и parent_post_id (can be null). (Если сообщение A отвечает на сообщение B, то A.parent_post_id = B.post_id). Моя проблема: написать запрос в oracle db, чтобы получить «длину цепи» для каждого сообщения. Я имею в виду: для каждого post_id я хочу знать, сколько есть вложенных дочерних элементов (так что это больше похоже на размер дерева, но пример цепочки также будет полезен) Я пробовал некоторые рекурсивные запросы, но в этом случае я беспомощен.

Fe. если стрелка (<-) означает «родитель». За A <- B <- C <- D хочу получить:

A 3
B 2
C 1
D 0

Ответы [ 2 ]

2 голосов
/ 28 января 2020

Я думаю, что вы после Oracle Иерархические запросы

WITH posts AS (
  SELECT 'A' AS post_id, null as parent_post_id FROM DUAL
  UNION
  SELECT 'B' AS post_id, 'A' as parent_post_id FROM DUAL
  UNION
  SELECT 'C' AS post_id, 'B' as parent_post_id FROM DUAL
  UNION
  SELECT 'D' AS post_id, 'C' as parent_post_id FROM DUAL
)
SELECT post_id, level AS chain_length
  FROM posts
 START WITH parent_post_id IS NULL
CONNECT BY PRIOR post_id = parent_post_id;

Вы можете сделать дерево более сложным, например, добавив B2 ответ к сообщению A, чтобы увидеть большее разнообразие представления данных, как вы могли бы видеть в реальном мире.

В моем примере я сделал отправную точку A, тогда как у вас это было D, не стесняйтесь изменять по своему усмотрению. Я также начал с 1, вы можете сделать это level - 1, если хотите иметь индекс на основе нуля.

1 голос
/ 28 января 2020

Иерархические запросы сделаны для вашего случая. Я немного расширил ваше дерево следующим образом:

A <- B <- C  <- D
     B <- C1 <- D1 
          C1 <- D2 

Если я вас правильно понял, следующие результаты являются желаемыми:

A   6
B   5
C   1
C1  2
D   0
D1  0
D2  0

Вот запрос:

with source_data as (
  select 'A' post_id, null parent_post_id from dual
  union
  select 'B' post_id, 'A' parent_post_id from dual
  union
  select 'C' post_id, 'B' parent_post_id from dual
  union
  select 'D' post_id, 'C' parent_post_id from dual
  union
  select 'C1' post_id, 'B' parent_post_id from dual
  union
  select 'D1' post_id, 'C1' parent_post_id from dual
  union
  select 'D2' post_id, 'C1' parent_post_id from dual
),
chains as (
  select connect_by_root post_id post_id, post_id child_post_id
  from source_data
  connect by nocycle prior post_id = parent_post_id
)
select post_id, count(1) - 1 chain_length
from   chains
group by post_id
order by 1

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...