Обычно я решаю эту проблему, синтезируя столбец «Путь», который можно отсортировать лексически, например, 0001:0003:0006:0009
является ребенком 0001:0003:0006
. Каждая дочерняя запись может быть создана путем объединения элемента path с путем родителя. Вам не нужно возвращать этот столбец клиенту, просто используйте его для сортировки.
id parent_comment_id user_id sort_key
9 null 30 0009
11 9 30 0009:0011
12 11 30 0009:0011:0012
13 12 31 0009:0011:0012:0013
10 null 30 0010
14 10 31 0010:0014
15 10 31 0010:0015
Элемент path не должен быть чем-то конкретным, если он сортирует лексически в том порядке, в котором вы хотите сортировать дочерние элементы на этом уровне, и уникален на этом уровне. Основываясь на автоматическом увеличении идентификатора, это хорошо.
Использование элемента пути фиксированной длины, строго говоря, не обязательно, но облегчает рассуждение.
WITH RECURSIVE CommentCTE AS (
SELECT id, parent_comment_id, user_id,
lpad(id::text, 4) sort_key
FROM comment
WHERE parent_comment_id is NULL
UNION ALL
SELECT child.id, child.parent_comment_id, child.user_id,
concat(CommentCTE.sort_key, ':', lpad(id::text, 4))
FROM comment child
JOIN CommentCTE
ON child.parent_comment_id = CommentCTE.id
)
SELECT * FROM CommentCTE order by sort_key