如何将多个逗号分隔值作为单独的列?
How to get multiple comma-separated values as individual columns?
我有一个 table 数据如下:
select * from data
id | col1 | col2 | col3
---+-------+-------+-------
1 | 1,2,3 | 4,5,6 | 7,8,9
我想获取这样的数据:
id | name | dd | fn | suf
---+------+----+----+-----
1 | col1 | 1 | 2 | 3
1 | col2 | 4 | 5 | 6
1 | col3 | 7 | 8 | 9
目前,我在这样的查询中使用 split_part():
SELECT * from(
select id,
'col1' as name,
NULLIF(split_part(col1, ',', 1), '') AS dd,
NULLIF(split_part(col1, ',', 2), '') AS fn,
NULLIF(split_part(col1, ',', 3), '') AS suf
from data
UNION
select id,
'col2' as name,
NULLIF(split_part(col2, ',', 1), '') AS dd,
NULLIF(split_part(col2, ',', 2), '') AS fn,
NULLIF(split_part(col2, ',', 3), '') AS suf
from data
UNION
select id,
'col3' as name,
NULLIF(split_part(col3, ',', 1), '') AS dd,
NULLIF(split_part(col3, ',', 2), '') AS fn,
NULLIF(split_part(col3, ',', 3), '') AS suf
from data
);
有没有更优雅的方式? 我有 20 列。
我会先做 union all
,然后做 split_part()
:
select id, name,
coalesce(split_part(col, ',', 1), '') as dd,
coalesce(split_part(col, ',', 2), '') as fn,
coalesce(split_part(col, ',', 3), '') as suf
from ((select id, 'col1' as name, col1 as col from data
) union all
(select id, 'col2' as name, col2 as col from data
) union all
(select id, 'col3' as name, col3 as col from data
)
) t;
假设这个 table:
CREATE TABLE tbl (id int, col1 text, col2 text, col3 text);
INSERT INTO tbl VALUES (1 ,'1,2,3', '4,5,6', '7,8,9');
LATERAL
子查询中的 VALUES
表达式应该是一个优雅的解决方案。
然后只需使用 split_part()
。仅当源中可能存在实际空字符串时才添加 NULLIF()
...
SELECT id, x.name
, split_part(x.col, ',', 1) AS dd
, split_part(x.col, ',', 2) AS fn
, split_part(x.col, ',', 3) AS suf
FROM tbl t, LATERAL (
VALUES (text 'col1', t.col1)
, ( 'col2', t.col2)
, ( 'col3', t.col3)
-- ... many more?
) x(name, col);
适用于 PostgreSQL 9.3 或更高版本。
SQL Fiddle.
相关:
Split comma separated column data into additional columns
我有一个 table 数据如下:
select * from data
id | col1 | col2 | col3
---+-------+-------+-------
1 | 1,2,3 | 4,5,6 | 7,8,9
我想获取这样的数据:
id | name | dd | fn | suf
---+------+----+----+-----
1 | col1 | 1 | 2 | 3
1 | col2 | 4 | 5 | 6
1 | col3 | 7 | 8 | 9
目前,我在这样的查询中使用 split_part():
SELECT * from(
select id,
'col1' as name,
NULLIF(split_part(col1, ',', 1), '') AS dd,
NULLIF(split_part(col1, ',', 2), '') AS fn,
NULLIF(split_part(col1, ',', 3), '') AS suf
from data
UNION
select id,
'col2' as name,
NULLIF(split_part(col2, ',', 1), '') AS dd,
NULLIF(split_part(col2, ',', 2), '') AS fn,
NULLIF(split_part(col2, ',', 3), '') AS suf
from data
UNION
select id,
'col3' as name,
NULLIF(split_part(col3, ',', 1), '') AS dd,
NULLIF(split_part(col3, ',', 2), '') AS fn,
NULLIF(split_part(col3, ',', 3), '') AS suf
from data
);
有没有更优雅的方式? 我有 20 列。
我会先做 union all
,然后做 split_part()
:
select id, name,
coalesce(split_part(col, ',', 1), '') as dd,
coalesce(split_part(col, ',', 2), '') as fn,
coalesce(split_part(col, ',', 3), '') as suf
from ((select id, 'col1' as name, col1 as col from data
) union all
(select id, 'col2' as name, col2 as col from data
) union all
(select id, 'col3' as name, col3 as col from data
)
) t;
假设这个 table:
CREATE TABLE tbl (id int, col1 text, col2 text, col3 text);
INSERT INTO tbl VALUES (1 ,'1,2,3', '4,5,6', '7,8,9');
LATERAL
子查询中的 VALUES
表达式应该是一个优雅的解决方案。
然后只需使用 split_part()
。仅当源中可能存在实际空字符串时才添加 NULLIF()
...
SELECT id, x.name
, split_part(x.col, ',', 1) AS dd
, split_part(x.col, ',', 2) AS fn
, split_part(x.col, ',', 3) AS suf
FROM tbl t, LATERAL (
VALUES (text 'col1', t.col1)
, ( 'col2', t.col2)
, ( 'col3', t.col3)
-- ... many more?
) x(name, col);
适用于 PostgreSQL 9.3 或更高版本。
SQL Fiddle.
相关:
Split comma separated column data into additional columns