U kunt dit bereiken met enkele van de json-functies beschikbaar in postgresql.
In het voorbeeld met werkende db-fiddle hieronder heb ik wat extra testgegevens toegevoegd.
Schema (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]}]}');
Vraag #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 ":"TweedeTest","bestemmingen":[{"Id":103},{"Id":105}]}]} |
{"DestinationLists":[{"name":"TV3/TVNZ/CHOICE","destinations":[{"Id":183},{"Id":165}]}]} |
Bewerk 1
Als reactie op uw bewerking kan de onderstaande code worden gebruikt als een update van de verklaring. NB. De CTE kan ook worden herschreven als een subquery. Zie het onderstaande voorbeeld:
Schema (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;
Na
SELECT * FROM my_table;
id | bestemming |
---|---|
1 | {"DestinationLists":[{"name":"TV3/TVNZ/CHOICE","destinations":[{"Id":183},{"Id":165}]}]} |
2 | {"DestinationLists":[{"name":"SecondTest","destinations":[{"Id":103},{"Id":105}]},{"name":"ThirdTest", "bestemmingen":[{"Id":3},{"Id":5}]}]} |
Bewerk 2
Deze bewerking reageert op de randgevallen waarbij sommige bestemmingen mogelijk geen bestemmingen hebben en als zodanig mogelijk niet worden bijgewerkt.
Om te testen zijn er twee extra records toegevoegd, het voorbeeldrecord met twee lijsten met benoemde bestemmingen, maar slechts één met bestemmingen en een andere met een benoemde bestemmingslijst zonder bestemmingen.
De update zorgt ervoor dat als er geen wijzigingen zijn, dat wil zeggen dat er lijsten met benoemde bestemmingen zijn zonder bestemmingen, deze hetzelfde blijven. Het verzekert dit door te controleren of het aantal benoemde bestemmingslijstitems hetzelfde is als het aantal lege bestemmingslijstitems. Omdat ze allemaal leeg zijn, filtert het deze record uit de update en vermindert het aantal vereiste updates voor de database. Een voorbeeld hiervan is recordnummer 4
De initiële zoekopdracht is aangepast om deze lege lijsten te kunnen bevatten, aangezien ze werden gefilterd met de vorige aanpak.
Schema (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": []}]}');
Vraag #1
SELECT '------ BEFORE -----';
?kolom? |
---|
------ VOOR ----- |
Vraag #2
SELECT * FROM my_table;
id | bestemming |
---|---|
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":"Vierde test","destinations":[]}]} |
Vraag #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", "bestemmingen":[{"Id":3},{"Id":5}]}]} |
3 | 2 | 1 | {"DestinationLists":[{"name":"TVNZ, Discovery","destinations":[{"Id":165},{"Id":183},{"Id":4155}]} ,{"name":"TVNZ, Mediaworks, Choice","bestemmingen":[]}]} |
Vraag #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;
Er zijn geen resultaten om weer te geven.
Vraag #5
SELECT '------ AFTER -----';
?kolom? |
---|
------ NA ----- |
Query #6
SELECT * FROM my_table;
id | bestemming |
---|---|
4 | {"DestinationLists":[{"name":"Vierde test","destinations":[]}]} |
1 | {"DestinationLists":[{"name":"TV3/TVNZ/CHOICE","destinations":[{"Id":183},{"Id":165}]}]} |
2 | {"DestinationLists":[{"name":"SecondTest","destinations":[{"Id":103},{"Id":105}]},{"name":"ThirdTest", "bestemmingen":[{"Id":3},{"Id":5}]}]} |
3 | {"DestinationLists":[{"name":"TVNZ, Discovery","destinations":[{"Id":165},{"Id":183},{"Id":4155}]} ,{"name":"TVNZ, Mediaworks, Choice","bestemmingen":[]}]} |
Laat me weten of dit voor jou werkt.