2011-12-21 94 views

回答

45

如果CSV字段的數量是恆定的,那麼你可以做這樣的事情:

select a[1], a[2], a[3], a[4] 
from (
    select regexp_split_to_array('a,b,c,d', ',') 
) as dt(a) 

例如:

=> 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) 

如果CSV字段數不恆定那麼你可以得到這樣的東西的最大數量:

select max(array_length(regexp_split_to_array(csv, ','), 1)) 
from your_table 

然後b爲您的查詢找到相應的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) 

如果你想,你可以將這兩個查詢組合成一個函數。

例如,給這個數據(這是最後一排的一個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) 

由於您的分隔符是一個簡單的固定字符串,你也可以使用string_to_array,而不是regexp_split_to_array

select ... 
from (
    select string_to_array(csv, ',') 
    from csvs 
) as dt(a); 

感謝Michael提醒有關此功能。

如果可能的話,您應該重新設計數據庫模式以避免使用CSV列。您應該使用數組列或單獨的表。

+0

感謝應檢查並恢復 – Gallop 2011-12-21 11:05:20

+6

考慮使用'string_to_array',而不是'regexp_split_to_array';它應該更快,因爲它沒有正則表達式處理的開銷。 – Michael 2014-09-15 06:46:18

+1

@Michael如果你願意,你可以添加它作爲另一個答案。或者我可以添加'string_to_array'作爲我的選項,不知道我是如何錯過的。 – 2014-09-16 04:53:24

64

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; 

添加儘可能多的行,你必須在col(最大可能)項目。超過數據項的列將爲空字符串('')。

+4

並且似乎比regexp_split_to_array版本執行速度快得多。 – 2014-04-01 10:05:28

+0

@JohnBarça:所有正則表達式函數都比較昂貴。強大的,但價格... – 2014-04-01 14:31:27

+4

傳說!這是迄今爲止這種問題最快的方法。 – 2016-03-16 14:14:38

1

您可以使用拆分功能。

SELECT 
    (select top 1 item from dbo.Split(FullName,',') where id=1) Column1, 
    (select top 1 item from dbo.Split(FullName,',') where id=2) Column2, 
    (select top 1 item from dbo.Split(FullName,',') where id=3) Column3, 
    (select top 1 item from dbo.Split(FullName,',') where id=4) Column4, 
    FROM MyTbl