如何将多个逗号分隔值作为单个列?

时间:2016-12-21 12:40:40

标签: sql postgresql split pivot delimiter

我有一个包含这样数据的表:

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列

2 个答案:

答案 0 :(得分:1)

假设这个表:

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');

VALUES子查询中的LATERAL表达式应该是一个优雅的解决方案 然后使用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.

相关:

答案 1 :(得分:0)

我会先union allsplit_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;