Redshiftで任意個数の文字列を扱う

最終的には縦持ちにしちゃえばどんなRDBでも扱えるんだけど、 某MySQLとか某Hadoopとかだと配列で持ってるじゃないですか。 ああいうのをどうやってとりこむか1年くらい考えてたんだけど ついに決定版を思いついた。

扱える個数の上限はあるんだけど、現実的にはほぼ上限を考えなくて済むと思う。

1. 文字列配列をJSONとしてRedshiftに取り込む

=> select * from slog order by 1;
id |    words    
----+---------------
  1 | ["a","b","c"]
  2 | ["xxx","yyy"]

2. 連番 1 カラムだけのテーブルを用意する

この連番テーブルのサイズが扱える個数の上限になってしまうので注意

=> select * from sseq order by 1;
 x 
---
 1
 2
 3
 4
 5

3. ジョインする

不等号でジョインするのがポイント

select
    slog.id
    , seq.x as param_id
    , json_extract_array_element_text(slog.words, seq.x - 1) as word
from
    slog inner join seq
    on seq.x <= json_array_length(slog.words)
order by 1, 2
;

4. なんと縦持ちになりました!

id | param_id | word 
----+----------+------
  1 |        1 | a
  1 |        2 | b
  1 |        3 | c
  2 |        1 | xxx
  2 |        2 | yyy

欠点

  • 連番テーブルのサイズで扱える個数の上限が決まる
  • Redshiftの文字列はかなり上限が短いので個数が多いと入りきらない