1 Test table data
SELECT relative_label_content FROM frk_s.label_cor_gene relative_label_content ------ AA BB CC
2 columns to change the line
Writing method 1:
string_agg
SELECT frwybs, string_agg (relative_label_content, ',') as relative_label_content FROM frk_s.label_cor_gene GROUP BY frwybs relative_label_content ------------ AA,BB,CC
Writing method 2:
array_to_string(ARRAY_AGG (text),',')
SELECT frwybs, array_to_string( ARRAY_AGG (DISTINCT relative_label_content), ',' ) as labels_content FROM frk_s.label_cor_gene GROUP BY frwybs labels_content ------------ AA,BB,CC
Supplement: PostgreSQL rank and column conversion (compatible with oracle pivot unpivot)
oracle11g has built-in pivot table function, which can be used to implement row and column conversion function, but the performance will be poor when the data volume is large.
The pivot syntax is:
SELECT ... FROM ... PIVOT [XML] (pivot_clause pivot_for_clause pivot_in_clause ) WHERE ...
Example of oracle pivot usage:
– Create a test table and insert data
create table usr (name varchar2(20), score int, class varchar2(20) ); insert into usr values('a',20,'math'); insert into usr values('a',22,'phy'); insert into usr values('b',23,'phy'); insert into usr values('b',21,'math'); insert into usr values('c',22,'phy'); insert into usr values('c',24,'math'); insert into usr values('d',25,'math'); insert into usr values('d',23,'phy');
– Use pivot for row and column conversion
SQL> select * from usr 2 pivot( sum(score) for class in ('math','phy') 3 4 5 ); NAME 'math' 'phy' -------------------- ---------- ---------- d 25 23 a 20 22 b 21 23 c 24 22
We can also use unpivot to achieve column-to-line conversion.
The unpivot syntax is:
SELECT ... FROM ... UNPIVOT [INCLUDE|EXCLUDE NULLS] (unpivot_clause unpivot_for_clause unpivot_in_clause ) WHERE ...
Example of oracle unpivot usage:
– Create a test table and insert data
CREATE TABLE t1 ( VendorID int, Emp1 int, Emp2 int, Emp3 int, Emp4 int, Emp5 int ); INSERT INTO t1 VALUES (1,4,3,5,4,4); INSERT INTO t1 VALUES (2,4,1,5,5,5); INSERT INTO t1 VALUES (3,4,3,5,4,4); INSERT INTO t1 VALUES (4,4,2,5,5,4); INSERT INTO t1 VALUES (5,5,1,5,5,5);
–Use unpivot for column conversion
SQL> select * from t1 2 UNPIVOT( orders for Employee in(emp1,emp2,emp3,emp4,emp5) ); 3 4 VENDORID EMPL ORDERS ---------- ---- ---------- 1 EMP1 4 1 EMP2 3 1 EMP3 5 1 EMP4 4 1 EMP5 4 2 EMP1 4 2 EMP2 1 2 EMP3 5 2 EMP4 5 2 EMP5 5 3 EMP1 4 VENDORID EMPL ORDERS ---------- ---- ---------- 3 EMP2 3 3 EMP3 5 3 EMP4 4 3 EMP5 4 4 EMP1 4 4 EMP2 2 4 EMP3 5 4 EMP4 5 4 EMP5 4 5 EMP1 5 5 EMP2 1 VENDORID EMPL ORDERS ---------- ---- ---------- 5 EMP3 5 5 EMP4 5 5 EMP5 5 25 rows selected.
So how to implement the rank-and-line conversion function of oracle's pivot/unpivot in pg? The tablefunc plugin that comes with pg can be implemented, and we can use the crossstab function interface in this plugin to perform row and column conversion.
Example of pg row to column:
– Create table and insert test data
create table tbl (seller text,se_year int,se_month int,se_amount int); insert into tbl values ('test1',2020,01,123456); insert into tbl values ('test1',2020,02,234567); insert into tbl values ('test1',2020,03,345678); insert into tbl values ('test1',2020,04,345678); insert into tbl values ('test1',2020,05,567890); insert into tbl values ('test2',2020,01,12); insert into tbl values ('test2',2020,02,23); insert into tbl values ('test2',2020,03,34); insert into tbl values ('test2',2020,04,45); insert into tbl values ('test2',2020,05,56); insert into tbl values ('test3',2020,03,12); insert into tbl values ('test3',2020,04,45); insert into tbl values ('test3',2020,05,56); insert into tbl values ('test4',2020,02,20); insert into tbl values ('test4',2020,03,30); insert into tbl values ('test4',2020,04,40); insert into tbl values ('test4',2020,05,50); insert into tbl values ('test1',2019,01,123456); insert into tbl values ('test1',2019,02,234567); insert into tbl values ('test1',2019,03,345678); insert into tbl values ('test1',2019,04,345678); insert into tbl values ('test1',2019,05,567890); insert into tbl values ('test1',2019,06,123456); insert into tbl values ('test1',2019,07,234567); insert into tbl values ('test1',2019,08,345678); insert into tbl values ('test1',2019,09,345678); insert into tbl values ('test1',2019,10,567890); insert into tbl values ('test1',2019,11,123456); insert into tbl values ('test1',2019,12,234567); insert into tbl values ('test2',2019,11,12); insert into tbl values ('test2',2019,12,23); insert into tbl select * from tbl;
– Row to column
bill=# select bill-# js->>'seller' as seller, bill-# js->>'se_year' as se_year, bill-# jan , bill-# feb , bill-# mar , bill-# apr , bill-# may , bill-# jun , bill-# jul , bill-# aug , bill-# sep , bill-# oct , bill-# nov , bill-# dec bill-# from crosstab( bill(# -- This is the source SQL and data source that requires row and column transformation.bill(# -- The sorting field is group by field, the last field is the converted content field, and the second field of the derivative is the row and column transform field (the content is an enum, such as a month)bill(# -- (All corresponding enum values must be extracted in the next parameter)bill(# $$select jsonb_build_object('seller', seller, 'se_year', se_year) as js, se_month, sum(se_amount) from tbl group by 1,2 order by 1$$, bill(# -- For rows converted by rows and columns, which values are extracted as columns. This represents the month here, which is the value of se_monthbill(# -- or (select * from (values('jan'),...('dec')) t(se_month))bill(# 'select distinct se_month from tbl order by 1' bill(# ) bill-# as -- crossstab output formatbill-# ( js jsonb, -- field corresponding to order by in the first parameter (1 or more)bill(# Jan numeric, -- The enumeration value of the second field corresponding to the derivative in the first parameter SQL (row to column)bill(# feb numeric, -- ...Same as abovebill(# mar numeric, bill(# apr numeric, bill(# may numeric, bill(# jun numeric, bill(# jul numeric, bill(# aug numeric, bill(# sep numeric, bill(# oct numeric, bill(# nov numeric, bill(# dec numeric bill(# ) bill-# order by 1,2; seller | se_year | jan | feb | mar | apr | may | jun | jul | aug | sep | oct | nov | dec --------+---------+--------+--------+--------+--------+---------+--------+--------+--------+--------+---------+--------+-------- test1 | 2019 | 246912 | 469134 | 691356 | 691356 | 1135780 | 246912 | 469134 | 691356 | 691356 | 1135780 | 246912 | 469134 test1 | 2020 | 246912 | 469134 | 691356 | 691356 | 1135780 | | | | | | | test2 | 2019 | | | | | | | | | | | 24 | 46 test2 | 2020 | 24 | 46 | 68 | 90 | 112 | | | | | | | test3 | 2020 | | | 24 | 90 | 112 | | | | | | | test4 | 2020 | | 40 | 60 | 80 | 100 | | | | | | | (6 rows)
– Column to row
bill=# with a as ( -- A corresponds to the original data (that is, the data that needs to be column-to-line)bill(# select bill(# js->>'seller' as seller, bill(# js->>'se_year' as se_year, bill(# jan , bill(# feb , bill(# mar , bill(# apr , bill(# may , bill(# jun , bill(# jul , bill(# aug , bill(# sep , bill(# oct , bill(# nov , bill(# dec bill(# from crosstab( bill(# -- This is the source SQL and data source that requires row and column transformation.bill(# -- The sorting field is group by field, the last field is the converted content field, and the second field of the derivative is the row and column transform field (the content is an enum, such as a month)bill(# -- (All corresponding enum values must be extracted in the next parameter)bill(# $$select jsonb_build_object('seller', seller, 'se_year', se_year) as js, se_month, sum(se_amount) from tbl group by 1,2 order by 1$$, bill(# -- For rows converted by rows and columns, which values are extracted as columns. This represents the month here, which is the value of se_monthbill(# -- or (select * from (values('jan'),...('dec')) t(se_month))bill(# 'select distinct se_month from tbl order by 1' bill(# ) bill(# as -- crossstab output formatbill(# ( js jsonb, -- field corresponding to order by in the first parameter (1 or more)bill(# Jan numeric, -- The enumeration value of the second field corresponding to the derivative in the first parameter SQL (row to column)bill(# feb numeric, -- ...Same as abovebill(# mar numeric, bill(# apr numeric, bill(# may numeric, bill(# jun numeric, bill(# jul numeric, bill(# aug numeric, bill(# sep numeric, bill(# oct numeric, bill(# nov numeric, bill(# dec numeric bill(# ) bill(# order by 1,2 bill(# ) bill-# , bill-# -- b , use jsonb to merge multiple columns into one column, and use jsonb_each to expand.bill-# b as (select seller, se_year, jsonb_each(row_to_json(a)::jsonb-'seller'::text-'se_year'::text) as rec from a) bill-# select seller, se_year, ().key as month, ().value as sum from b; seller | se_year | month | sum --------+---------+-------+--------- test1 | 2019 | apr | 691356 test1 | 2019 | aug | 691356 test1 | 2019 | dec | 469134 test1 | 2019 | feb | 469134 test1 | 2019 | jan | 246912 test1 | 2019 | jul | 469134 test1 | 2019 | jun | 246912 test1 | 2019 | mar | 691356 test1 | 2019 | may | 1135780 test1 | 2019 | nov | 246912 test1 | 2019 | oct | 1135780 test1 | 2019 | sep | 691356 test1 | 2020 | apr | 691356 test1 | 2020 | aug | null test1 | 2020 | dec | null test1 | 2020 | feb | 469134 test1 | 2020 | jan | 246912 test1 | 2020 | jul | null test1 | 2020 | jun | null test1 | 2020 | mar | 691356 test1 | 2020 | may | 1135780 test1 | 2020 | nov | null test1 | 2020 | oct | null test1 | 2020 | sep | null test2 | 2019 | apr | null test2 | 2019 | aug | null test2 | 2019 | dec | 46 test2 | 2019 | feb | null test2 | 2019 | jan | null test2 | 2019 | jul | null test2 | 2019 | jun | null test2 | 2019 | mar | null test2 | 2019 | may | null test2 | 2019 | nov | 24 test2 | 2019 | oct | null test2 | 2019 | sep | null test2 | 2020 | apr | 90 test2 | 2020 | aug | null test2 | 2020 | dec | null test2 | 2020 | feb | 46 test2 | 2020 | jan | 24 test2 | 2020 | jul | null test2 | 2020 | jun | null test2 | 2020 | mar | 68 test2 | 2020 | may | 112 test2 | 2020 | nov | null test2 | 2020 | oct | null test2 | 2020 | sep | null test3 | 2020 | apr | 90 test3 | 2020 | aug | null test3 | 2020 | dec | null test3 | 2020 | feb | null test3 | 2020 | jan | null test3 | 2020 | jul | null test3 | 2020 | jun | null test3 | 2020 | mar | 24 test3 | 2020 | may | 112 test3 | 2020 | nov | null test3 | 2020 | oct | null test3 | 2020 | sep | null test4 | 2020 | apr | 80 test4 | 2020 | aug | null test4 | 2020 | dec | null test4 | 2020 | feb | 40 test4 | 2020 | jan | null test4 | 2020 | jul | null test4 | 2020 | jun | null test4 | 2020 | mar | 60 test4 | 2020 | may | 100 test4 | 2020 | nov | null test4 | 2020 | oct | null test4 | 2020 | sep | null (72 rows)
The above is personal experience. I hope you can give you a reference and I hope you can support me more. If there are any mistakes or no complete considerations, I would like to give you advice.