I am developing a database for a forum, with threads and messages. Threads start with a message with no parent_id; replies are messages with parent_id.
I have a table for the messages. Each item reference to items on same table, to relate them as parent-child.
create table messages(
id int,
title text,
content text,
parent_id int
);
Now I fill the table with some Data:
insert into messages values
(1, 'One', 'First thread main post', null), -- First thread
(2, 'Two', 'First thread reply', 1),
(3, 'Three', 'First thread reply', 2),
(4, 'Four', 'Second thread main post', null), -- Second thread
(5, 'Five', 'Second thread reply', 4),
(6, 'Six', 'Second thread reply', 5),
(7, 'Six', 'Second thread reply', 6),
(8, 'Six', 'Second thread reply', 7),
(9, 'Six', 'Second thread reply', 8);
Knowing the id of the first message of a thread, I can retrieve all replies with a recursive query:
with recursive my_tree as (
select * from messages
where parent_id IS null and id = 4
union all
select messages.* from messages
join my_tree on messages.parent_id = my_tree.id
) select my_tree.*
from my_tree;
Here is a fiddle.
Now, lets say I know the id of some reply, and I want to get the id of the first message of the thread. How can I do it?
EDIT:
I know I can retrieve all messages of a thread from the known id upwards:
with recursive my_tree as (
select * from messages
where id = 9
union all
select messages.* from messages
join my_tree on messages.id = my_tree.parent_id
) select my_tree.*
from my_tree;
Here a fiddle. But if the thread consists of thousands of messages that would be less than efficient. Is there any way a recursive query can get to first item without retrieving all messages?