これは、いくつかのjson関数 で実現できます。 postgresqlで利用できます。
以下のdb-fiddleを使用した例では、いくつかの追加のテストデータを含めました。
スキーマ(PostgreSQL v13)
CREATE TABLE my_table (
"dest" json
);
INSERT INTO my_table
("dest")
VALUES
('{"DestinationLists": [{"name": "TV3/TVNZ/CHOICE", "destinations": [183, 165]}]}'),
('{"DestinationLists": [{"name": "SecondTest", "destinations": [103, 105]},{"name": "ThirdTest", "destinations": [3, 5]}]}');
クエリ#1
WITH expanded_data AS (
SELECT
dest::text,
json_build_object(
'name',
dl->>'name',
'destinations',
json_agg(
json_build_object('Id',dld::text::int)
)
) as dest_list_item
FROM
my_table,
json_array_elements(dest->'DestinationLists') dl,
json_array_elements(dl->'destinations') dld
GROUP BY
dest::text,dl->>'name'
)
SELECT
json_build_object(
'DestinationLists',
json_agg(dest_list_item)
) as new_dest
FROM
expanded_data
GROUP BY
dest::text;
new_dest |
---|
{"DestinationLists":[{"name": "ThirdTest"、 "destinations":[{"Id":3}、{"Id":5}]}、{"name ":" SecondTest "、" destinations ":[{" Id ":103}、{" Id ":105}]}]} |
{"DestinationLists":[{"name": "TV3 / TVNZ / CHOICE"、 "destinations":[{"Id":183}、{"Id":165}]}]} |
編集1
編集に応じて、以下のコードをステートメントからの更新として使用できます。注意。 CTEは、サブクエリとして書き直すこともできます。以下の例をご覧ください:
スキーマ(PostgreSQL v13)
CREATE TABLE my_table (
id bigserial,
"dest" jsonb
);
INSERT INTO my_table
("dest")
VALUES
('{"DestinationLists": [{"name": "TV3/TVNZ/CHOICE", "destinations": [183, 165]}]}'),
('{"DestinationLists": [{"name": "SecondTest", "destinations": [103, 105]},{"name": "ThirdTest", "destinations": [3, 5]}]}');
WITH expanded_data AS (
SELECT
id,
json_build_object(
'name',
dl->>'name',
'destinations',
json_agg(
json_build_object('Id',dld::text::int)
)
) as dest_list_item
FROM
my_table,
jsonb_array_elements(dest->'DestinationLists') dl,
jsonb_array_elements(dl->'destinations') dld
GROUP BY
id,dl->>'name'
),
new_json AS (
SELECT
id,
json_build_object(
'DestinationLists',
json_agg(dest_list_item)
) as new_dest
FROM
expanded_data
GROUP BY
id
)
UPDATE my_table
SET dest = new_json.new_dest
FROM new_json
WHERE my_table.id = new_json.id;
後
SELECT * FROM my_table;
id | 宛先 |
---|---|
1 | {"DestinationLists":[{"name": "TV3 / TVNZ / CHOICE"、 "destinations":[{"Id":183}、{"Id":165}]}]} |
2 | {"DestinationLists":[{"name": "SecondTest"、 "destinations":[{"Id":103}、{"Id":105}]}、{"name": "ThirdTest"、 "destinations":[{"Id":3}、{"Id":5}]}]} |
編集2
この編集は、一部の宛先に宛先がないために更新されない可能性があるエッジケースに対応します。
テストするために、2つの追加レコードが追加されました。サンプルレコードは、2つの名前付き宛先リストがあり、1つだけに宛先があり、もう1つには宛先のない名前付き宛先リストがある場合に提供されます。
この更新により、変更がない場合、つまり、宛先が同じままである宛先リストがないことが保証されます。名前付き宛先リスト項目の数が空の宛先リスト項目の数と同じであるかどうかをチェックすることにより、これを保証します。すべてが空であるため、更新からこのレコードをフィルタリングし、データベースで必要な更新の数を減らします。この例は、レコード番号4
です。
最初のクエリは、以前のアプローチでフィルタリングされていたため、これらの空のリストに対応するように変更されました。
スキーマ(PostgreSQL v13)
CREATE TABLE my_table (
id bigserial,
"dest" jsonb
);
INSERT INTO my_table
("dest")
VALUES
('{"DestinationLists": [{"name": "TV3/TVNZ/CHOICE", "destinations": [183, 165]}]}'),
('{"DestinationLists": [{"name": "SecondTest", "destinations": [103, 105]},{"name": "ThirdTest", "destinations": [3, 5]}]}'),
('{"DestinationLists": [{"name": "TVNZ, Mediaworks, Choice", "destinations": []}, {"name": "TVNZ, Discovery", "destinations": [165, 183, 4155]}]}'),
('{"DestinationLists": [{"name": "Fourth Test", "destinations": []}]}');
クエリ#1
SELECT '------ BEFORE -----';
?column? |
---|
------ BEFORE ----- |
クエリ#2
SELECT * FROM my_table;
id | 宛先 |
---|---|
1 | {"DestinationLists":[{"name": "TV3 / TVNZ / CHOICE"、 "destinations":[183,165]}]} |
2 | {"DestinationLists":[{"name": "SecondTest"、 "destinations":[103,105]}、{"name": "ThirdTest"、 "destinations":[3,5]}]} |
3 | {"DestinationLists":[{"name": "TVNZ、Mediaworks、Choice"、 "destinations":[]}、{"name": "TVNZ、Discovery"、 "destinations":[165,183,4155] }]} |
4 | {"DestinationLists":[{"name": "Fourth Test"、 "destinations":[]}]} |
クエリ#3
WITH expanded_data AS (
SELECT
id,
CASE
WHEN COUNT(dld)=0 THEN 1
ELSE 0
END as name_has_empty_list_item,
json_build_object(
'name',
dl->>'name',
'destinations',
CASE
WHEN
COUNT(dld)=0
THEN
to_json(array[]::json[])
ELSE
json_agg(
json_build_object('Id',dld::text::int )
)
END
) as dest_list_item
FROM
my_table,
jsonb_array_elements(dest->'DestinationLists') dl
LEFT JOIN
jsonb_array_elements(dl->'destinations') dld ON 1=1
GROUP BY
id,dl->>'name'
),
new_json AS (
SELECT
id,
COUNT(dest_list_item) as no_list_item,
SUM(name_has_empty_list_item) as no_empty_list_item,
json_build_object(
'DestinationLists',
json_agg(dest_list_item)
) as new_dest
FROM
expanded_data
GROUP BY
id
HAVING
SUM(name_has_empty_list_item) <> COUNT(dest_list_item)
)
SELECT * FROM new_json;
id | no_list_item | no_empty_list_item | new_dest |
---|---|---|---|
1 | 1 | 0 | {"DestinationLists":[{"name": "TV3 / TVNZ / CHOICE"、 "destinations":[{"Id":183}、{"Id":165}]}]} |
2 | 2 | 0 | {"DestinationLists":[{"name": "SecondTest"、 "destinations":[{"Id":103}、{"Id":105}]}、{"name": "ThirdTest"、 "destinations":[{"Id":3}、{"Id":5}]}]} |
3 | 2 | 1 | {"DestinationLists":[{"name": "TVNZ、Discovery"、 "destinations":[{"Id":165}、{"Id":183}、{"Id":4155}]} 、{"name": "TVNZ、Mediaworks、Choice"、 "destinations":[]}]} |
クエリ#4
WITH expanded_data AS (
SELECT
id,
CASE
WHEN COUNT(dld)=0 THEN 1
ELSE 0
END as name_has_empty_list_item,
json_build_object(
'name',
dl->>'name',
'destinations',
CASE
WHEN
COUNT(dld)=0
THEN
to_json(array[]::json[])
ELSE
json_agg(
json_build_object('Id',dld::text::int )
)
END
) as dest_list_item
FROM
my_table,
jsonb_array_elements(dest->'DestinationLists') dl
LEFT JOIN
jsonb_array_elements(dl->'destinations') dld ON 1=1
GROUP BY
id,dl->>'name'
),
new_json AS (
SELECT
id,
json_build_object(
'DestinationLists',
json_agg(dest_list_item)
) as new_dest
FROM
expanded_data
GROUP BY
id
HAVING
SUM(name_has_empty_list_item) <> COUNT(dest_list_item)
)
UPDATE my_table
SET dest = new_json.new_dest
FROM new_json
WHERE my_table.id = new_json.id;
表示する結果はありません。
クエリ#5
SELECT '------ AFTER -----';
?column? |
---|
------ AFTER ----- |
クエリ#6
SELECT * FROM my_table;
id | 宛先 |
---|---|
4 | {"DestinationLists":[{"name": "Fourth Test"、 "destinations":[]}]} |
1 | {"DestinationLists":[{"name": "TV3 / TVNZ / CHOICE"、 "destinations":[{"Id":183}、{"Id":165}]}]} |
2 | {"DestinationLists":[{"name": "SecondTest"、 "destinations":[{"Id":103}、{"Id":105}]}、{"name": "ThirdTest"、 "destinations":[{"Id":3}、{"Id":5}]}]} |
3 | {"DestinationLists":[{"name": "TVNZ、Discovery"、 "destinations":[{"Id":165}、{"Id":183}、{"Id":4155}]} 、{"name": "TVNZ、Mediaworks、Choice"、 "destinations":[]}]} |
これでうまくいくかどうか教えてください。