PostgreSQLのJSONデータ型をYellowfinから利用する


最近の主要なRDB製品ではJSONデータがサポートされています。
Yellowfinからそのようなデータを利用するにはどうすればいいのか、PostgreSQLを例にとって試してみます。

# データ準備

テスト用のテーブルを作ってJSON形式のデータを投入します。

```sql:
CREATE TABLE json_test (id integer, col_1 json, col_2 jsonb);

INSERT INTO json_test VALUES (
  1,
  '{ "title": "Book the First",  "author": { "last_name": "鈴木", "first_name": "一郎" }, "age": 30 }',
  '{ "publish": { "publisher": "Yellowfin出版", "pubdate": "2017-01-01"}, "category": "技術" }'
);
INSERT INTO json_test VALUES (
  2,
  '{ "title": "Book the Second",  "author": { "last_name": "田中", "first_name": "太郎" }, "age": 43 }',
  '{ "publish": { "publisher": "マグロ社", "pubdate": "2017-03-31"}, "category": "歴史" }'
);
INSERT INTO json_test VALUES (
  3,
  '{ "title": "Book the Third",  "author": { "last_name": "山田", "first_name": "花子" }, "age": 32 }',
  '{ "publish": { "publisher": "ツナ書房", "pubdate": "2017-07-22"}, "category": "文学" }'
);

```

PostgreSQLのJSONデータ型には、テキストのままデータを保持する```json```型と、バイナリに変換して保持する```jsonb```型の2種類があります。処理効率の側面から、ほとんどの場合はjsonb型を用いるのが望ましいようですが、その点についてここでは論じませんので詳しくはググってみてください。
Yellowfinからの動作確認のため、上記ではjson型とjsonb型のそれぞれを作っています。

突っ込んだデータはこんな感じで見えます。

```txt:
sandbox=# SELECT * FROM json_test;
 id |                                                col_1                                                |                                          col_2
----+-----------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------
  1 | { "title": "Book the First",  "author": { "last_name": "鈴木", "first_name": "一郎" }, "age": 30 }  | {"publish": {"pubdate": "2017-01-01", "publisher": "Yellowfin出版"}, "category": "技術"}
  2 | { "title": "Book the Second",  "author": { "last_name": "田中", "first_name": "太郎" }, "age": 43 } | {"publish": {"pubdate": "2017-03-31", "publisher": "マグロ社"}, "category": "歴史"}
  3 | { "title": "Book the Third",  "author": { "last_name": "山田", "first_name": "花子" }, "age": 32 }  | {"publish": {"pubdate": "2017-07-22", "publisher": "ツナ書房"}, "category": "文学"}
(3 rows)
```

ネストされたデータを取得するには以下のようなSQLを投げます。

```txt:
sandbox=# SELECT id, col_1->'author'->>'last_name' as last_name, col_2->'publish'->>'publisher' as publisher FROM json_test;
 id | last_name |   publisher
----+-----------+---------------
  1 | 鈴木      | Yellowfin出版
  2 | 田中      | マグロ社
  3 | 山田      | ツナ書房
(3 rows)
```

# Yellowfinからの利用

## データソースとビューの作成

いつもの手順で、Yellowfin上にデータソースとビューを作成していきます。

ただ、ビューの「モデル」の時点ではデータの中身も見られるのですが…

![scan1.png](https://qiita-image-store.s3.amazonaws.com/0/116818/c3e908f3-e9cb-5699-2009-399f8d04e2c8.png "scan1.png")

「準備」へ進むとJSONデータ型のカラムは「データ型不明」となり、中身が表示されなくなってしまいます。

![scan2.png](https://qiita-image-store.s3.amazonaws.com/0/116818/21d5d4c4-d86f-84f0-ab1e-7e4de7a9db12.png "scan2.png")

このままでは扱えないので、データを変換してやる必要があります。

## フリーハンドSQL計算フィールドの作成

そこで使用するのがYellowfinの「計算フィールド」です。
計算フィールドは項目間の四則演算やCASE式による条件分岐のために使用することが一般的ですが、直接SQLを記述する「フリーハンドSQL」の機能も備わっています。

例えば、上記データのpublisherを取得する場合なら、以下のように設定します。

```txt:
col_2->'publish'->>'publisher'
```

![scan3.png](https://qiita-image-store.s3.amazonaws.com/0/116818/f6bc3283-9332-af59-8c10-eda2b5e3ce32.png "scan3.png")

他にも、last_nameとfirst_nameを連結するなら、

```txt:
concat(col_1->'author'->>'last_name', col_1->'author'->>'first_name')
```

pubdateをDate型に変換するには、

```txt:
to_date(col_2->'publish'->>'pubdate', 'YYYY-MM-DD')
```

ageを数値型にしたければ、

```txt:
to_number(col_1->>'age', '99')
```

といった具合に定義するとYellowfinで扱いやすいデータになります。

![scan4.png](https://qiita-image-store.s3.amazonaws.com/0/116818/b5e47cf0-257d-7b79-4eb5-ad3058a68386.png "scan4.png")

当然、レポートも普通に作れます。

![scan5.png](https://qiita-image-store.s3.amazonaws.com/0/116818/7d58bc6d-89c5-7055-7144-3f14254f6b46.png "scan5.png")

今回はビューでフリーハンドSQLの計算フィールドを作成しましたが、レポートでフリーハンドSQLの計算フィールドを作成したり、あるいはレポート自体をフリーハンドSQLで作成する方法を取ることも可能です。

# 参考

https://community.yellowfinbi.com/knowledge-base/article/what-is-a-json-data-type-and-does-yellowfin-support-it