PostgreSQLでJSONBを用いたデータ結合【PostgreSQL】

## 説明

データをJSONBに変換して結合する方法

1.　テーブル定義。
```sql
-- 業務日付
CREATE TABLE work_day (
    user_id SERIAL,
    work_date DATE,
    PRIMARY KEY (user_id, work_date)
);
-- 主務
CREATE TABLE work_main (
    user_id SERIAL,
    work_code VARCHAR,
    start_date DATE,
    end_date DATE,
    etc VARCHAR,
    PRIMARY KEY (user_id, work_code, start_date)
);
-- 副務
CREATE TABLE work_sub (
    user_id SERIAL,
    work_code VARCHAR,
    start_date DATE,
    end_date DATE,
    etc VARCHAR,
    PRIMARY KEY (user_id, work_code, start_date)
);
```
2.　サンプルデータ
```text
-- 業務日付
user_id	work_date
1	2024/10/01
1	2024/10/02
1	2024/10/03
1	2024/10/04
1	2024/10/05
2	2024/10/01
2	2024/10/02
2	2024/10/03
2	2024/10/04
2	2024/10/05
3	2024/10/01
3	2024/10/02
3	2024/10/03
3	2024/10/04
3	2024/10/05

-- 主務
user_id	work_code	start_date	end_date
1	A001	2024/10/01	2024/10/03
1	A001	2024/10/02	2024/10/04
1	A001	2024/10/03	2024/10/05
2	B001	2024/10/01	2024/10/03
2	B001	2024/10/02	2024/10/04
2	B001	2024/10/03	2024/10/05
3	C001	2024/10/01	2024/10/03
3	C001	2024/10/02	2024/10/04
3	C001	2024/10/03	2024/10/05

-- 副務
user_id	work_code	start_date	end_date
1	X001	2024/10/01	2024/10/03
1	X001	2024/10/02	2024/10/04
1	X001	2024/10/03	2024/10/05
2	Y001	2024/10/01	2024/10/03
2	Y001	2024/10/02	2024/10/04
2	Y001	2024/10/03	2024/10/05
3	Z001	2024/10/01	2024/10/03
3	Z001	2024/10/02	2024/10/04
3	Z001	2024/10/03	2024/10/05
```
3.　`WITH`で`各テーブルの情報をJSONB形式でまとめるサブクエリを作成。
4.　業務日付とサブクエリで作成したJSONを結合して取得。
```sql
-- 各テーブルの情報をJSONB形式でまとめるサブクエリを作成
WITH work_main_json AS (
    SELECT
        wm.user_id,
        wd.work_date,
        jsonb_agg(jsonb_build_object(
            'user_id', wm.user_id,
            'work_code', wm.work_code,
            'start_date', wm.start_date,
            'end_date', wm.end_date,
            'etc', wm.etc
        )) AS work_main_json
    FROM
        work_day wd
    LEFT JOIN work_main wm 
        ON wd.user_id = wm.user_id 
        AND wd.work_date BETWEEN wm.start_date AND wm.end_date
    GROUP BY
        wm.user_id, wd.work_date
),
work_sub_json AS (
    SELECT
        ws.user_id,
        wd.work_date,
        jsonb_agg(jsonb_build_object(
            'user_id', ws.user_id,
            'work_code', ws.work_code,
            'start_date', ws.start_date,
            'end_date', ws.end_date,
            'etc', ws.etc
        )) AS work_sub_json
    FROM
        work_day wd
    LEFT JOIN work_sub ws 
        ON wd.user_id = ws.user_id 
        AND wd.work_date BETWEEN ws.start_date AND ws.end_date
    GROUP BY
        ws.user_id
        , wd.work_date
)

-- メインクエリでLEFT JOINを使用してサブクエリと結合
SELECT
    wd.user_id,
    wd.work_date,
    wmj.work_main_json,
    wsj.work_sub_json
FROM
    work_day wd 
    LEFT JOIN work_main_json wmj 
        ON wd.user_id = wmj.user_id 
        AND wd.work_date = wmj.work_date 
    LEFT JOIN work_sub_json wsj 
        ON wd.user_id = wsj.user_id 
        AND wd.work_date = wsj.work_date 
ORDER BY
    wd.user_id
    , wd.work_date;

```
5.　取得結果
```
user_id	work_date	work_main_json	work_sub_json
1	2024/10/01	[{"etc": null, "user_id": 1, "end_date": "2024-10-03", "work_code": "A001", "start_date": "2024-10-01"}]	[{"etc": null, "user_id": 1, "end_date": "2024-10-03", "work_code": "X001", "start_date": "2024-10-01"}]
1	2024/10/02	[{"etc": null, "user_id": 1, "end_date": "2024-10-03", "work_code": "A001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 1, "end_date": "2024-10-04", "work_code": "A001", "start_date": "2024-10-02"}]	[{"etc": null, "user_id": 1, "end_date": "2024-10-03", "work_code": "X001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 1, "end_date": "2024-10-04", "work_code": "X001", "start_date": "2024-10-02"}]
1	2024/10/03	[{"etc": null, "user_id": 1, "end_date": "2024-10-03", "work_code": "A001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 1, "end_date": "2024-10-04", "work_code": "A001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 1, "end_date": "2024-10-05", "work_code": "A001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 1, "end_date": "2024-10-03", "work_code": "X001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 1, "end_date": "2024-10-04", "work_code": "X001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 1, "end_date": "2024-10-05", "work_code": "X001", "start_date": "2024-10-03"}]
1	2024/10/04	[{"etc": null, "user_id": 1, "end_date": "2024-10-04", "work_code": "A001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 1, "end_date": "2024-10-05", "work_code": "A001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 1, "end_date": "2024-10-04", "work_code": "X001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 1, "end_date": "2024-10-05", "work_code": "X001", "start_date": "2024-10-03"}]
1	2024/10/05	[{"etc": null, "user_id": 1, "end_date": "2024-10-05", "work_code": "A001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 1, "end_date": "2024-10-05", "work_code": "X001", "start_date": "2024-10-03"}]
2	2024/10/01	[{"etc": null, "user_id": 2, "end_date": "2024-10-03", "work_code": "B001", "start_date": "2024-10-01"}]	[{"etc": null, "user_id": 2, "end_date": "2024-10-03", "work_code": "Y001", "start_date": "2024-10-01"}]
2	2024/10/02	[{"etc": null, "user_id": 2, "end_date": "2024-10-03", "work_code": "B001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 2, "end_date": "2024-10-04", "work_code": "B001", "start_date": "2024-10-02"}]	[{"etc": null, "user_id": 2, "end_date": "2024-10-03", "work_code": "Y001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 2, "end_date": "2024-10-04", "work_code": "Y001", "start_date": "2024-10-02"}]
2	2024/10/03	[{"etc": null, "user_id": 2, "end_date": "2024-10-03", "work_code": "B001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 2, "end_date": "2024-10-04", "work_code": "B001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 2, "end_date": "2024-10-05", "work_code": "B001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 2, "end_date": "2024-10-03", "work_code": "Y001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 2, "end_date": "2024-10-04", "work_code": "Y001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 2, "end_date": "2024-10-05", "work_code": "Y001", "start_date": "2024-10-03"}]
2	2024/10/04	[{"etc": null, "user_id": 2, "end_date": "2024-10-04", "work_code": "B001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 2, "end_date": "2024-10-05", "work_code": "B001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 2, "end_date": "2024-10-04", "work_code": "Y001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 2, "end_date": "2024-10-05", "work_code": "Y001", "start_date": "2024-10-03"}]
2	2024/10/05	[{"etc": null, "user_id": 2, "end_date": "2024-10-05", "work_code": "B001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 2, "end_date": "2024-10-05", "work_code": "Y001", "start_date": "2024-10-03"}]
3	2024/10/01	[{"etc": null, "user_id": 3, "end_date": "2024-10-03", "work_code": "C001", "start_date": "2024-10-01"}]	[{"etc": null, "user_id": 3, "end_date": "2024-10-03", "work_code": "Z001", "start_date": "2024-10-01"}]
3	2024/10/02	[{"etc": null, "user_id": 3, "end_date": "2024-10-03", "work_code": "C001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 3, "end_date": "2024-10-04", "work_code": "C001", "start_date": "2024-10-02"}]	[{"etc": null, "user_id": 3, "end_date": "2024-10-03", "work_code": "Z001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 3, "end_date": "2024-10-04", "work_code": "Z001", "start_date": "2024-10-02"}]
3	2024/10/03	[{"etc": null, "user_id": 3, "end_date": "2024-10-03", "work_code": "C001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 3, "end_date": "2024-10-04", "work_code": "C001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 3, "end_date": "2024-10-05", "work_code": "C001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 3, "end_date": "2024-10-03", "work_code": "Z001", "start_date": "2024-10-01"}, {"etc": null, "user_id": 3, "end_date": "2024-10-04", "work_code": "Z001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 3, "end_date": "2024-10-05", "work_code": "Z001", "start_date": "2024-10-03"}]
3	2024/10/04	[{"etc": null, "user_id": 3, "end_date": "2024-10-04", "work_code": "C001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 3, "end_date": "2024-10-05", "work_code": "C001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 3, "end_date": "2024-10-04", "work_code": "Z001", "start_date": "2024-10-02"}, {"etc": null, "user_id": 3, "end_date": "2024-10-05", "work_code": "Z001", "start_date": "2024-10-03"}]
3	2024/10/05	[{"etc": null, "user_id": 3, "end_date": "2024-10-05", "work_code": "C001", "start_date": "2024-10-03"}]	[{"etc": null, "user_id": 3, "end_date": "2024-10-05", "work_code": "Z001", "start_date": "2024-10-03"}]

```