2017-10-17 4 views
0

に複数列に単一動的な列を分割する:赤方偏移は次のようにテーブルを持つ新しいテーブル

 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 

セグメントの数は動的であり、変化することができる:持つ新しいテーブルを作成する方法

 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 

各レコードで 区切り文字で分割関数を試しましたが、ここでは動的な文字列のインデックスが必要です。

提案がありますか?

+0

を除外する交差どうして? – jarlh

+0

ここではダイナミックなものは何ですか?あなたの例でindex = 1を使用しています - 説明するためにいくつかの異なるサンプルを表示してください –

+0

私は質問を理解しています - あなたの答えは全く異なるので、あなたが使っているものだけにタグを変更してください! –

答えて

4

これはRedshiftの回答です.1行あたり最大10,000のセグメント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(セグメントの最大数)と等しい数の行を取ります。

最終的に、私たちは、あなたがいくつかのDBMS製品をタグ付け、入力データとスプリッタを結合split_partを使用して、関連する値をとり、その後、(行はセグメントの<最大数を有する場合に生じる)ブランク部分

+0

魅力のように働く。まだどのように把握しようとしています。私はインデックスの部分を取得しますが、元のテーブルのようにUIDとどのようにマッチさせていますか? –

+0

なぜten_numbersで1000,100,10のような値を使用していますか? –

+0

これは10000行の出力を生成しています。各行に対してgen_numをインクリメントします。通常はこれのためにgenerate_series関数を使用することができますが、これは赤方偏移では不可能ですので、これは賢明な回避策です。あなたが10000を必要としないなら、その部分を削除することができます。しかしこれには事実上オーバーヘッドはありません。 –

関連する問題