Reputation: 721
I have a data set like below(PostgresQL version 11),I want to add a sorting column to this with decimal points so that i can easily map the parent - child tree in my visualisation.
Any method or query we can do that,Tried with row number and rank but that is not helping.
Data Set:
Parent Child
Vitamine Vitamine
Vitamin D Vitamin D
Vitamin D Vitamin D3
Vitamin D Vitamin D K2
Vitamin D D3
Vitamin D Vitamin D 1000
Vitamin D Vitamin D 10000
Vitamin D Vitamin D 20000
Vitamin K2 Vitamin K2
Vitamin K2 Vitamin K
Vitamin K2 Vitamin K2 Mk7
Vitamin C Vitamin C
Expected out put
Parent Child Sort_order
Vitamine Vitamine 1
Vitamin D Vitamin D 2
Vitamin D Vitamin D3 2.1
Vitamin D Vitamin D K2 2.2
Vitamin D D3 2.3
Vitamin D Vitamin D 1000 2.4
Vitamin D Vitamin D 10000 2.5
Vitamin D Vitamin D 20000 2.6
Vitamin K2 Vitamin K2 3
Vitamin K2 Vitamin K 3.1
Vitamin K2 Vitamin K2 Mk7 3.2
Vitamin C Vitamin C 4
Upvotes: 0
Views: 210
Reputation: 943
Considering the following table schema:
create table vitamins (
id serial primary key,
parent_id integer,
name varchar(64),
index smallint
);
with the following data:
insert into vitamins (id, parent_id, name, index) values
(1, null, 'Vitamine', 1),
(2, null, 'Vitamin D', 2),
(3, 2, 'Vitamin D3', 1),
(4, 2, 'Vitamin D K2', 2),
(5, 2, 'D3', 3),
(6, 2, 'Vitamin D 1000', 4),
(7, 2, 'Vitamin D 10000', 5),
(8, 2, 'Vitamin D 20000', 6),
(9, null, 'Vitamin K2', 3),
(10, 9, 'Vitamin K', 1),
(11, 9, 'Vitamin K2 Mk7', 2),
(12, null, 'Vitamin C', 4)
;
We can get the expected output you want with the following query:
WITH RECURSIVE recursive_vitamins(id, parent_id, index, parent_name, name, ref, sort) AS (
SELECT c.id, c.parent_id, c.index, c.name, c.name, c.index::text, lpad(c.index::text, 3, '0')
FROM vitamins c
WHERE parent_id is null
UNION ALL
SELECT c.id, c.parent_id, c.index, rc.parent_name, c.name,
CASE WHEN rc.ref = '' THEN c.index::text
ELSE (rc.ref || '.' || c.index)
END, (rc.sort || '.' || lpad(c.index::text, 3, '0'))
FROM vitamins c, recursive_vitamins rc
WHERE c.parent_id = rc.id
)
SELECT
parent_name AS parent,
name AS child,
ref AS sort_order
FROM recursive_vitamins
ORDER BY sort;
Result:
parent child sort_order
Vitamine Vitamine 1
Vitamin D Vitamin D 2
Vitamin D Vitamin D3 2.1
Vitamin D Vitamin D K2 2.2
Vitamin D D3 2.3
...
(sqlfiddle of the whole thing)
Hold up, what's happening here?
So, we create a recursive CTE allowing the query to refer to it's own output.
In the WITH
query we first select all parents (parent_id is null
) then we select all childs that refer to the the parent_id
.
The ref
field is a concatenation of parent and child index. The sort
field refers to index
as well, but it left-pads the index
with 0
to a total length of 3. You could leave this out and just order by ref
, but if you have an index
>= 10
, the order would become 1, 10, 10.1, 2
which I would guess you don't want.
Upvotes: 1