1

I have a table like this to save the catalog of 90 services:

-------------------------------------------------------------------------------------
| id | service | subservice | description | cost
-------------------------------------------------------------------------------------
| 2044 | Tests | Tests | Calcium | 50.00
| 1385 | Cardiology | Cardioversion | Electric Cardioversion programmed| 200.00
| 7000 | Cardiology | Ecocardiography| Chest Ultrasound | 100.00
-------------------------------------------------------------------------------------

I need to change the table structure in order to have the three levels (service, subservice and description) in the same column with its own id and pointing to a new column with the level's number. Namely something like this (note that the id's are something that I made up):

-------------------------------------------------------------------------------------
| id | description | parent_id | cost
-------------------------------------------------------------------------------------
| 1 | Tests | NULL | 0.00
| 2 | Tests | 1 | 0.00
| 2044 | Calcium | 2 | 50.00
-------------------------------------------------------------------------------------

I'm working on Postgresql 12. I have created the new column parent_id and I was trying to do this sequence:

CREATE SEQUENCE seq_parent_id INCREMENT BY 1 START WITH 1 NO CYCLE;
ALTER TABLE catalog
ALTER COLUMN parent_id SET DEFAULT nextval('seq_parent_id')

Can anyone please give a rough idea how to transform the structure of the table?

asked May 29, 2021 at 7:59
2
  • First .... You can not use sequence on parent_id table. Sencond do you want to store the existing data into new transformed table? Commented May 29, 2021 at 8:39
  • Yes, I want to store the existing data into the new transform table. Commented May 29, 2021 at 8:41

1 Answer 1

1

Its a bit lengthy, So the steps are:

  1. Old Table
create table test (id int, service varchar, subservice varchar, description varchar, cost decimal(10,2));
  1. New Table
create table newtest(id int, description varchar, parent_id int, cost decimal(10,2));
  1. Create a sequence as you have mentioned in your question
CREATE SEQUENCE seq_parent_id INCREMENT BY 1 START WITH 1 NO CYCLE;
  1. Now Run below query
with cte(id, description, parent_id,cost) as 
(select nextval('seq_parent_id'), service, null::bigint,0::decimal 
from test group by 2
),
cte1(id, description, parent_id,cost) as 
(select nextval('seq_parent_id'), subservice, t2.id,0::decimal 
from test t1 
inner join cte t2 on t1.service=t2.description and t2.parent_id is null group by 2,3
)
insert into newtest
select * from cte
union all
select * from cte1
union all
select t1.id,t1.description,t3.id,t1.cost from test t1 
inner join cte t2 on t1.service=t2.description and t2.parent_id is null
inner join cte1 t3 on t1.subservice=t3.description and t3.parent_id=t2.id

DEMO

Explanation of above query is demonstrated in this fiddle

NOTE: Before running the query please ensure that counter value will not cross the already existing ID. If newly inserted rows are more than minimum existing count then set the start of sequence max(id)+1 before running this query.

answered May 29, 2021 at 9:27
6
  • This is great, thank you. I was stuck there, I did not know how to do it with CTE. Commented May 29, 2021 at 11:55
  • One thing, is it possible to do this without creating a new table? Thanks. Commented May 29, 2021 at 14:19
  • then where you will store new data, in same table? Commented May 29, 2021 at 14:20
  • I was thinking in the same table test and dropping service and subservice columns. Commented May 29, 2021 at 14:22
  • 1
    Actually it will be all together a different question. This is the fiddle for your additional question. Commented May 29, 2021 at 14:35

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.