У меня сейчас проблема. У меня есть таблица мест с такой структурой:
Я хочу сделать выбор, чтобы иметь всю иерархию этой таблицы. Вот небольшой пример данных:
(1, null, '123 Barclay St')
(2, 1, 'Floor 1')
(3, 1, 'Floor 2')
(4, 1, 'Floor 3')
(5, 2, 'Hall 1')
(6, 2, 'Room 1')
(7, 2, 'Room 2')
(8, 3, 'Room 3')
(9, null, '10 Thames St')
Очевидно, что порядок в таблице не такой.
Итак, я хочу получить этот результат с помощью моего SELECT (с 9 строками):
123 Barclay St
Floor 1
Hall 1
Room 1
Room 2
Floor 2
Room 3
Floor 3
10 Thames St
И не этот результат (который я уже знаю, как получить):
10 Thames St
123 Barclay St
Floor 1
Floor 2
Floor 3
Hall 1
Room 1
Room 2
Room 3
Если вы можете мне помочь, заранее благодарю вас.


Вот решение с использованием рекурсивных CTE:
WITH RECURSIVE cte AS (
SELECT LPAD(id::text, 3, '0') AS marker, ' ' AS buffer,
id, parent_id, name::text
FROM yourTable t WHERE parent_id IS NULL
FROM yourTable t WHERE parent_id IS NULL
UNION ALL
SELECT t2.marker || ':' || LPAD(t1.parent_id::text, 3, '0') || ':' ||
LPAD(t1.id::text, 3, '0') AS marker,
t2.buffer || ' ', t1.id, t1.parent_id, t2.buffer || t1.name
FROM yourTable t1
INNER JOIN cte t2
ON t1.parent_id = t2.id
)
SELECT name FROM cte ORDER BY marker;
Основная идея здесь состоит в том, чтобы построить строки пути, которые отслеживают полный путь от каждого узла, идущего к его корню (корень задается узлом, чей parent_id - это NULL). Затем мы просто выполняем один ORDER BY на этом пути, чтобы сгенерировать нужный вам порядок.
@ S.Kaio Использование массивов немного проще: dbfiddle.uk/… И, кроме того, вы получаете простой в использовании путь для каждого элемента.
@Abelisto Я протестировал ваше решение и мне очень понравилось. Спасибо за помощь :)
Вы не предоставили запросы, которые у вас уже были. Но, насколько я понимаю, вам нужна рекурсивная древовидная структура.
https://www.db-fiddle.com/f/og5HZDHBhBRmP1cDnqgCBB/1
CREATE TABLE rooms (
id INTEGER, parent_id INTEGER, name TEXT
);
INSERT INTO rooms VALUES
(1, null, '123 Barclay St'),
(2, 1, 'Floor 1'),
(3, 1, 'Floor 2'),
(4, 1, 'Floor 3'),
(5, 2, 'Hall 1'),
(6, 2, 'Room 1'),
(7, 2, 'Room 2'),
(8, 3, 'Room 3'),
(9, null, '10 Thames St');
И запрос:
WITH RECURSIVE tree AS (
SELECT
rooms.id,
rooms.parent_id,
rooms.name
FROM
rooms
WHERE
parent_id IS NULL
UNION ALL
SELECT
rooms.id,
rooms.parent_id,
rooms.name
FROM
tree
JOIN rooms ON rooms.parent_id = tree.id
)
SELECT
*
FROM
tree;
https://www.postgresql.org/docs/current/static/queries-with.html
Извините, если я не предоставлю уже возникшие вопросы, но я сказал, что результат мне не нужен. Я сделал ваш запрос перед этой публикацией, и этот запрос дает мне плохой результат, о котором я сказал. Он возвращает следующую иерархию: Barclay St, Floor 1, Floor 2, Floor 3, Hall 1, ... но не со всей иерархией по уровням. Большое вам спасибо за то, что вы пытались мне помочь. :)
Я пробовал это решение и подтверждаю его. Большое спасибо.