将逗号分隔的列数据拆分为其他列

Gal*_*lop 61 postgresql split delimiter postgresql-8.4

我在列中有逗号分隔的数据:

Column 
------- 
a,b,c,d 
Run Code Online (Sandbox Code Playgroud)

我想将逗号分隔数据拆分为多个列以获得此输出:

Column1  Column2 Column3 Column4 
-------  ------- ------- -------
a        b       c       d 
Run Code Online (Sandbox Code Playgroud)

怎么能实现这一目标?

Erw*_*ter 92

split_part() 一步完成你想做的事:

SELECT split_part(col, ',', 1) AS col1
     , split_part(col, ',', 2) AS col2
     , split_part(col, ',', 3) AS col3
     , split_part(col, ',', 4) AS col4
FROM   tbl;
Run Code Online (Sandbox Code Playgroud)

添加尽可能多的项目col(可能的最大值).超出数据项的列将为空字符串('').

  • 传说!到目前为止,这是解决此类问题的最快方法. (7认同)
  • 并且似乎比regexp_split_to_array版本执行得快得多. (6认同)

mu *_*ort 63

如果CSV中的字段数是常数,那么您可以执行以下操作:

select a[1], a[2], a[3], a[4]
from (
    select regexp_split_to_array('a,b,c,d', ',')
) as dt(a)
Run Code Online (Sandbox Code Playgroud)

例如:

=> select a[1], a[2], a[3], a[4] from (select regexp_split_to_array('a,b,c,d', ',')) as dt(a);
 a | a | a | a 
---+---+---+---
 a | b | c | d
(1 row)
Run Code Online (Sandbox Code Playgroud)

如果CSV中的字段数不是常数,那么您可以使用以下内容获得最大字段数:

select max(array_length(regexp_split_to_array(csv, ','), 1))
from your_table
Run Code Online (Sandbox Code Playgroud)

然后a[1], a[2], ..., a[M]为您的查询构建适当的列列表.因此,如果上面给出的最大值为6,那​​么你可以使用:

select a[1], a[2], a[3], a[4], a[5], a[6]
from (
    select regexp_split_to_array(csv, ',')
    from your_table
) as dt(a)
Run Code Online (Sandbox Code Playgroud)

如果需要,可以将这两个查询组合成一个函数.

例如,提供此数据(在最后一行中为NULL):

=> select * from csvs;
     csv     
-------------
 1,2,3
 1,2,3,4
 1,2,3,4,5,6

(4 rows)

=> select max(array_length(regexp_split_to_array(csv, ','), 1)) from csvs;
 max 
-----
   6
(1 row)

=> select a[1], a[2], a[3], a[4], a[5], a[6] from (select regexp_split_to_array(csv, ',') from csvs) as dt(a);
 a | a | a | a | a | a 
---+---+---+---+---+---
 1 | 2 | 3 |   |   | 
 1 | 2 | 3 | 4 |   | 
 1 | 2 | 3 | 4 | 5 | 6
   |   |   |   |   | 
(4 rows)
Run Code Online (Sandbox Code Playgroud)

由于您的分隔符是一个简单的固定字符串,您也可以使用string_to_array而不是regexp_split_to_array:

select ...
from (
    select string_to_array(csv, ',')
    from csvs
) as dt(a);
Run Code Online (Sandbox Code Playgroud)

感谢Michael提供有关此功能的提醒.

您真的应该重新设计数据库架构,以便尽可能避免使用CSV列.您应该使用数组列或单独的表.

  • 考虑使用`string_to_array`而不是`regexp_split_to_array`; 它应该更快,因为它没有正则表达式处理的开销. (9认同)
  • @DennisBauszus:很好.你也查过`split_part`了吗?只是好奇. (2认同)