У меня есть таблица идентификаторов некоторых книг. Таблица называется prequel и имеет два столбца: «resid» и «prequelid». Если пара идентификаторов присутствует в виде строки в этой таблице, это означает, что значение "prequelid" является преквелом значения "resid". Как я могу написать запрос, который для каждой серии книг соединяет все приквелы/продолжения серии в правильном порядке? Пример: книги серии «Властелин колец» имеют следующие идентификаторы: B1002, B1003, B1004. Я хочу, чтобы строка для этой серии выглядела так (один столбец с названием серия): B1002 => B1003 => B1004

Возможно, это можно сделать рекурсивно? С CONCAT()? Помните, что я использую Postgres, и синтаксис может отличаться от MySQL или SQL Server.

Может ли кто-нибудь написать запрос, который делает это? Идентификаторы имеют определенный домен CHAR(5). Предположим, что ни одна книга не может иметь более одного приквела.


 resid | prequelid
-------+-----------
 B1003 | B1002
 B1004 | B1003
 B5002 | B5001
 B5003 | B5002
 B5004 | B5003
 B5005 | B5004
 B5006 | B5005
 B5007 | B5006
(8 rows)

В этом случае в результате запроса будет 2 строки. Один ряд с 3 книгами (серия «Властелин колец») и другой ряд с 7 книгами (серия «Гарри Поттер»).

0
user12095666 12 Ноя 2019 в 15:17

1 ответ

Я думаю, это то, что вы хотите:

with recursive cte as
      (select b.prequelid, b.resid, b.prequelid || '=>' || b.resid as path, 1 as lev
       from books b
       where not exists (select 1 from books b2 where b2.resid = b.prequelid)
       union all
       select cte.prequelid, b.resid, path || '=>' || b.resid, lev + 1
       from cte join
            books b
            on cte.resid = b.prequelid
       where lev < 5
      )
select distinct on (prequelid) *
from cte
order by prequelid, lev desc;

Вот db<>скрипка.

0
Gordon Linoff 12 Ноя 2019 в 15:25