Reputation: 43
I have two tables with a relation 1-n. I'm looking for the way to order my elements. I could use a column "position(int)" but i prefer to use the id of the precedence :
+-------+---------------+-------+
| pk_id | precedence_id | fk_id |
+-------+---------------+-------+
| 4 | 1 | 10 |
+-------+---------------+-------+
| 1 | 6 | 10 |
+-------+---------------+-------+
| 2 | 5 | 40 |
+-------+---------------+-------+
| 3 | NULL | 10 |
+-------+---------------+-------+
| 6 | 3 | 10 |
+-------+---------------+-------+
| 5 | NULL | 40 |
+-------+---------------+-------+
I have a primary key (pk_id), a foreign key (fk_id) and a precedence constraint on the same table (precedence_id).
I am looking for the query to get the result with the precedence :
+-------+---------------+-------+
| pk_id | precedence_id | fk_id |
+-------+---------------+-------+
| 3 | NULL | 10 |
+-------+---------------+-------+
| 6 | 3 | 10 |
+-------+---------------+-------+
| 1 | 6 | 10 |
+-------+---------------+-------+
| 4 | 1 | 10 |
+-------+---------------+-------+
| 5 | NULL | 40 |
+-------+---------------+-------+
| 2 | 5 | 40 |
+-------+---------------+-------+
SELECT *
FROM tb
ORDER BY fk_id, ??
Upvotes: 0
Views: 104
Reputation: 43
This is working properly :
WITH RECURSIVE recursive(pk_id, precedence_id, position) AS (
SELECT pk_id, precedence_id, 0
FROM tb
WHERE precedence_id ISNULL
UNION ALL
SELECT v.pk_id, v.precedence_id, rec.position + 1
FROM
tb v
INNER JOIN recursive rec ON rec.pk_id = v.precedence_id
)
SELECT tst.*, rec.position
FROM
recursive rec
INNER JOIN tb tst ON rec.pk_id = tst.pk_id
ORDER BY tst.fk_id, rec.position;
Upvotes: 1
Reputation: 812
with recursive t (pk_id,path,L_name) as (
select pk_id
,array[pk_id]
,coalesce(precedence_id,0) as L_tree -- can be representative relation_name
,precedence_id
,fk_id
from tb
where coalesce(precedence_id,0) = 0
union all
select el.pk_id
,t.path || array[el.pk_id]
,coalesce(el.precedence_id,0) as L_tree -- can be representative relation_name
,coalesce(el.precedence_id,0) as precedence_id
,el.fk_id
from tb as el
join t on (el.precedence_id= t.pk_id)
where el.pk_id <> any (t.path))
select pk_id
,cast(case when array_upper(path,1)>1 then ' ' else '' end || repeat(' ', array_upper(path,1)-2)||L_name as character varying(1000)) as L_tree
,precedence_id
,array_upper(path,1) as tree_level
,fk_id from t
order by path
Try using recursive with. I dug this up from one of my old projects.
Edit: Found a similar example hierarchical data in postgres
Upvotes: 0
Reputation: 31993
use precedence_id in order by
clause
select * from tb
order by fk_id,precedence_id desc,pk_id
http://sqlfiddle.com/#!17/ba4b8/5
Upvotes: 0