Você pode usar uma
cross join
e filtrando:select t1.post_title, t2.post_title, t3.post_title
from t t1 cross join
t t2 cross join
t t3
where t1.category_id = 1 and
t2.category_id = 2 and
t3.category_id = 3;
Você pode generalizar isso usando um CTE recursivo:
with recursive tt as (
select t.*, dense_rank() over (order by category_id) as cat_seqnum
from t
),
cte as (
select cat_seqnum, post_title
from tt
where cat_seqnum = 1
union all
select tt.cat_seqnum, concat_ws('-', cte.post_title, tt.post_title)
from cte join
tt
on tt.cat_seqnum = cte.cat_seqnum + 1
)
select *
from cte
where cat_seqnum = (select max(cat_seqnum) from tt);
Aqui é um db<>fiddle.