Puoi ottenere questo risultato con alcune delle funzioni json disponibile in postgresql.
Nell'esempio con db-fiddle funzionante di seguito ho incluso alcuni dati di test aggiuntivi.
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]}]}');
Richiesta n. 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}]}]} |
Modifica 1
In risposta alla tua modifica, il codice seguente può essere utilizzato come aggiornamento dalla dichiarazione. NB. Il CTE può anche essere riscritto come subquery. Si prega di vedere l'esempio seguente:
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;
Dopo
SELECT * FROM my_table;
id | destinazione |
---|---|
1 | {"DestinationLists":[{"name":"TV3/TVNZ/CHOICE","destinations":[{"Id":183},{"Id":165}]}]} |
2 | {"DestinationLists":[{"name":"SecondTest","destinations":[{"Id":103},{"Id":105}]},{"name":"TerzoTest", "destinazioni":[{"Id":3},{"Id":5}]}]} |
Modifica 2
Questa modifica risponde ai casi limite in cui alcune destinazioni potrebbero non avere destinazioni e pertanto potrebbero non essere aggiornate.
Per verificare, sono stati aggiunti due record aggiuntivi, il record di esempio fornito in cui sono presenti due elenchi di destinazioni con nome ma solo uno ha destinazioni e un altro in cui è presente un elenco di destinazioni con nome senza destinazioni.
L'aggiornamento garantisce che se non ci sono modifiche, cioè ci sono elenchi di destinazioni con nome senza destinazioni che rimangono gli stessi. Lo assicura controllando se il numero di voci dell'elenco di destinazione con nome è uguale al numero di voci dell'elenco di destinazione vuote. Poiché tutti sono vuoti, filtra questo record dall'aggiornamento e riduce il numero di aggiornamenti richiesti nel database. Un esempio è il numero di record 4
La query iniziale è stata modificata per accogliere questi elenchi vuoti poiché venivano filtrati con l'approccio precedente.
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": []}]}');
Richiesta n. 1
SELECT '------ BEFORE -----';
?colonna? |
---|
------ PRIMA ----- |
Richiesta n. 2
SELECT * FROM my_table;
id | destinazione |
---|---|
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":"Quarto test","destinations":[]}]} |
Richiesta n. 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":"TerzoTest", "destinazioni":[{"Id":3},{"Id":5}]}]} |
3 | 2 | 1 | {"DestinationLists":[{"name":"TVNZ, Discovery","destinations":[{"Id":165},{"Id":183},{"Id":4155}]} ,{"name":"TVNZ, Mediaworks, Choice","destinations":[]}]} |
Richiesta n. 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;
Non ci sono risultati da visualizzare.
Richiesta n. 5
SELECT '------ AFTER -----';
?colonna? |
---|
------ DOPO ----- |
Richiesta n. 6
SELECT * FROM my_table;
id | destinazione |
---|---|
4 | {"DestinationLists":[{"name":"Quarto test","destinations":[]}]} |
1 | {"DestinationLists":[{"name":"TV3/TVNZ/CHOICE","destinations":[{"Id":183},{"Id":165}]}]} |
2 | {"DestinationLists":[{"name":"SecondTest","destinations":[{"Id":103},{"Id":105}]},{"name":"TerzoTest", "destinazioni":[{"Id":3},{"Id":5}]}]} |
3 | {"DestinationLists":[{"name":"TVNZ, Discovery","destinations":[{"Id":165},{"Id":183},{"Id":4155}]} ,{"name":"TVNZ, Mediaworks, Choice","destinations":[]}]} |
Fammi sapere se questo funziona per te.