Sto utilizzando array_to_json in combinazione con array_agg per formattare determinati risultati in PostgreSQL come JSON. Funziona bene per le query in cui voglio restituire il valore predefinito di una query (tutte le colonne, non modificato). Ma sono perplesso su come potrei usare array_agg per creare un oggetto JSON per una query in cui voglio modificare parte dell'output.Applicazione array_agg/array_to_json a una query con colonne modificate
Ecco un esempio. Diciamo che abbiamo la seguente:
CREATE TABLE temp_user (
user_id serial PRIMARY KEY,
real_name text
);
CREATE TABLE temp_user_ip (
user_id integer,
ip_address text
);
INSERT INTO temp_user (user_id, real_name) VALUES (1, 'Elise'), (2, 'John'), (3, NULL);
INSERT INTO temp_user_ip (user_id, ip_address) VALUES (1, '10.0.0.4'), (2, '10.0.0.7'), (3, '10.0.0.9');
la seguente query funziona bene:
# SELECT array_to_json(array_agg(temp_user)) as users from temp_user;
users
-----------------------------------------------------------------------------------------------------
[{"user_id":1,"real_name":"Elise"},{"user_id":2,"real_name":"John"},{"user_id":3,"real_name":null}]
Ma diciamo che non mi piace il valore null che appare per l'utente 3. Preferisco vedere la stringa "Utente connesso da $ ip" invece.
posso fare questo:
# SELECT user_id, (CASE WHEN real_name IS NULL THEN (select 'User logged in from ' || ip_address FROM temp_user_ip WHERE user_id = temp_user.user_id) ELSE real_name END) as name from temp_user;
E io ottenere i seguenti risultati:
user_id | name
---------+------------------------------
1 | Elise
2 | John
3 | User logged in from 10.0.0.9
che è grande. Ma non riesco a capire come manipolare questi dati nel formato JSON come il primo esempio.
L'uscita desiderata è ovviamente il seguente:
[{"user_id":1,"name":"Elise"},{"user_id":2,"name":"John"},{"user_id":3,"name":"User logged in from 10.0.0.9"}]
Il seguente non funziona:
# select array_to_json(array_agg ((SELECT user_id, (CASE WHEN real_name IS NULL THEN (select 'User logged in from ' || ip_address FROM temp_user_ip WHERE user_id = temp_user.user_id) ELSE real_name END) as name from temp_user)));
ERROR: subquery must return only one column
non riesco a capire un modo per ottenere i dati in un formato che array_agg accetta. Ho persino provato a creare un tipo personalizzato che corrispondesse al formato di temp_user e che cercasse di eseguire le chiamate array_agg al costruttore del tipo, che restituiva lo stesso errore. L'errore non ha senso per me - se la subquery è aggregata, allora non dovrebbe importare se restituisce più di una colonna. Qualche consiglio?
Posso confermare questo funziona; Ho appena applicato questo metodo correttamente alla mia domanda reale. Grazie! – hs0
La query può essere semplificata un po 'sostituendo 'array_agg (row (t. *))' Semplicemente 'array_agg (t)'. In questo modo manterrai anche i nomi delle colonne dalla sottoquery. –