2017-10-17 27 views
0

拆分單個動態列分成多個列與表等:紅移在新表

 uid    |   segmentids 
-------------------------+---------------------------------------- 
f9b6d54b-c646-4bbb-b0ec | 4454918|4455158|4455638|4455878|4455998 
asd7a0s9-c646-asd7-b0ec | 1265899|1265923|1265935|1266826|1266596 
gd3355ff-cjr8-assa-fke0 | 2237557|2237581|2237593 
laksnfo3-kgi5-fke0-b0ec | 4454918|4455158|4455638|4455878 

如何創建一個新的表:

 uid    |   segmentids 
-------------------------+--------------------------- 
f9b6d54b-c646-4bbb-b0ec |   4454918 
f9b6d54b-c646-4bbb-b0ec |   1265899 
f9b6d54b-c646-4bbb-b0ec |   2237557 
f9b6d54b-c646-4bbb-b0ec |   4454918 
f9b6d54b-c646-4bbb-b0ec |   4454918 
asd7a0s9-c646-asd7-b0ec |   1265899 
asd7a0s9-c646-asd7-b0ec |   1265923 
asd7a0s9-c646-asd7-b0ec |   1265935 
asd7a0s9-c646-asd7-b0ec |   1266826 
asd7a0s9-c646-asd7-b0ec |   1266596 

段的數目是動態的,可以變化與每個記錄。 我試着用分隔符分割函數,但它需要字符串中的索引,這裏是動態的。

有什麼建議嗎?

+0

您標籤幾個DBMS產品,怎麼來的? – jarlh

+0

這是什麼動態?您在示例中使用了index = 1 - 請示出一些不同的示例來解釋請 –

+0

我明白這個問題 - 請將您的標籤更改爲您正在使用的標籤,因爲答案完全不同! –

回答

4

這裏是Redshift的答案,它每行最多可以處理10000個segment ID值。

測試數據

create table test_split (uid varchar(50),segmentids varchar(max)); 
insert into test_split 
    values 
     ('f9b6d54b-c646-4bbb-b0ec','4454918|4455158|4455638|4455878|4455998'), 
     ('asd7a0s9-c646-asd7-b0ec','1265899|1265923|1265935|1266826|1266596'), 
     ('asd7345s9-c646-asd7-b0ec','1235935|1263456|1265675696'), 
     ('as345a0s9-c646-asd7-b0ec','12765899|12658883|12777935|144466826|1266226|12345') 
; 

代碼

with ten_numbers as (select 1 as num union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 0) 
    , generted_numbers AS 
(
    SELECT (1000 * t1.num) + (100 * t2.num) + (10 * t3.num) + t4.num AS gen_num 
    FROM ten_numbers AS t1 
     JOIN ten_numbers AS t2 ON 1 = 1 
     JOIN ten_numbers AS t3 ON 1 = 1 
     JOIN ten_numbers AS t4 ON 1 = 1 
) 
    , splitter AS 
(
    SELECT * 
    FROM generted_numbers 
    WHERE gen_num BETWEEN 1 AND (SELECT max(REGEXP_COUNT(segmentids, '\\|') + 1) 
           FROM test_split) 
) 
    --select * from splitter; 
    , expanded_input AS 
(
    SELECT 
     uid, 
     split_part(segmentids, '|', s.gen_num) AS segment 
    FROM test_split AS ts 
     JOIN splitter AS s ON 1 = 1 
    WHERE split_part(segmentids, '|', s.gen_num) <> '' 
) 
SELECT * FROM expanded_input; 

第一2個CTE步驟(ten_numbers和generated_numbers)被用於產生一個數量的行的,這是必要的,因爲generate_series不支持

下一步(拆分器)只需要等於最大分隔符數+1(這是最大分段數)的行數

最後,我們CROSS JOIN分路器與輸入數據,使用split_part採取相關的值,然後排除空白部分(這是造成其中行有<段的最大數量)

+0

像魅力一樣工作。仍在試圖弄清楚如何。我得到索引部分,但你如何與原始表中的uid匹配呢? –

+0

爲什麼我們在10_number中使用1000,100和10等值? –

+0

它產生10000行輸出。 gen_num遞增每行。通常你可以使用generate_series函數來實現,但這在redshift中是不可能的,所以這是一個聰明的解決方法。如果你不需要10000,那麼你可以刪除那部分。這樣做實際上沒有任何開銷。 –