Reputation: 109
I have a table as below
I want to split the column OWNERS at delimiter ',' and create new columns.
No of columns to be created depends on owners in OWNERS column. There is no MAX count for names in OWNERS column.
Expected result is as below .
Requesting help
Upvotes: 1
Views: 2641
Reputation: 4448
If you have data as following:
Lease | Owner |
---|---|
L1 | Benson,Greene,Lacy |
L2 | Walter,Amson |
L3 | Rustin |
L4 | Thomas,Justin,Greene,Lacy |
You can use a Dynamic Pivot query to split comma delimited text into columns as following:
with tabular_data as (
select *
from leases,
table(split_to_table(owners, ','))
)
select *
from tabular_data
pivot (min(value) for index in (ANY));
This will produce:
LEASE | OWNERS | SEQ | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|---|
L4 | Thomas,Justin,Greene,Lacy | 4 | Thomas | Justin | Greene | Lacy |
L3 | Rustin | 3 | Rustin | |||
L2 | Walter,Amson | 2 | Walter | Amson | ||
L1 | Benson,Greene,Lacy | 1 | Benson | Greene | Lacy |
Upvotes: 0
Reputation: 26003
Data:
create table table_a as
select * from values
('L1','Benson,Greene,Lacy'),
('L2','Walter,Amson'),
('L3','Rustin'),
('L4','Thomas,Justin,Greene,Lacy')
;
hand sql as per Dave's answer:
select
column1 as lease,
nullif(split_part(column2,',',1),'') owner1,
nullif(split_part(column2,',',2),'') owner2,
nullif(split_part(column2,',',3),'') owner3,
nullif(split_part(column2,',',4),'') owner4
from table_a;
the max number is:
select max(array_size(split(column2,','))) from table_a;
MAX(ARRAY_SIZE(SPLIT(COLUMN2,','))) |
---|
4 |
so lets make the first SQL dynamically:
declare
sql text;
maximum_count integer;
begin
select max(array_size(split(column2,','))) into :maximum_count from table_a;
sql := 'select column1 as lease';
for i in 1 to maximum_count do
sql := sql || ' ,nullif(split_part(column2,'','','|| i ||'),'''') owner'||i;
end for;
sql := sql || ' from table_a;';
return sql;
end;
anonymous block |
---|
select column1 as lease ,nullif(split_part(column2,',',1),'') owner1 ,nullif(split_part(column2,',',2),'') owner2 ,nullif(split_part(column2,',',3),'') owner3 ,nullif(split_part(column2,',',4),'') owner4 from table_a; |
so now lets call that and return those results:
declare
sql text;
maximum_count integer;
res resultset;
begin
select max(array_size(split(column2,','))) into :maximum_count from table_a;
sql := 'select column1 as lease';
for i in 1 to maximum_count do
sql := sql || ' ,nullif(split_part(column2,'','','|| i ||'),'''') owner'||i;
end for;
sql := sql || ' from table_a;';
res := (execute immediate :sql);
return table (res);
end;
if you are still running in the old UI:
execute immediate $$
declare
sql text;
maximum_count integer;
res resultset;
begin
select max(array_size(split(column2,','))) into :maximum_count from test.public.table_a;
sql := 'select column1 as lease';
for i in 1 to maximum_count do
sql := sql || ' ,nullif(split_part(column2,'','','|| i ||'),'''') owner'||i;
end for;
sql := sql || ' from table_a;';
res := (execute immediate :sql);
return table (res);
end;
$$
;
Upvotes: 2
Reputation: 1926
This works for 4 owners. For an unlimited number of owners, you will probably need to build the SQL string interactively and then EXECUTE IMMEDIATE.
Source: Pivot ANYTHING in Snowflake, Without the SQL PIVOT Function which includes information about the pivot option.
with t(lease,owners) as (
select * from values
('L1','Benson,Greene,Lacy'),
('L2','Walter,Amson'),
('L3','Rustin'),
('L4','Thomas,Justin,Greene,Lacy')
)
select
lease,
iff(split_part(owners,',',1)<>'',split_part(owners,',',1),'') owner1,
iff(split_part(owners,',',2)<>'',split_part(owners,',',2),'') owner2,
iff(split_part(owners,',',3)<>'',split_part(owners,',',3),'') owner3,
iff(split_part(owners,',',4)<>'',split_part(owners,',',4),'') owner4
from t;
LEASE | OWNER1 | OWNER2 | OWNER3 | OWNER4 |
---|---|---|---|---|
L1 | Benson | Greene | Lacy | |
L2 | Walter | Amson | ||
L3 | Rustin | |||
L4 | Thomas | Justin | Greene | Lacy |
Upvotes: 0