Używam array_to_json w połączeniu z array_agg do formatowania określonych wyników w PostgreSQL jako JSON. Działa to dobrze dla zapytań, w których chcę zwrócić domyślną wartość zapytania (wszystkie kolumny, niezmodyfikowane). Ale jestem zakłopotany, jak mogę użyć array_agg do utworzenia obiektu JSON dla zapytania, w którym chcę zmodyfikować niektóre dane wyjściowe.Stosowanie array_agg/array_to_json do zapytania z zmodyfikowanymi kolumnami
Oto przykład. Powiedzmy, że mamy następujące:
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');
Następująca kwerenda działa prawidłowo:
# 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}]
Ale powiedzmy, że nie podoba mi się wartość zerową dla użytkownika pojawiające 3. Wolałbym zobaczyć zamiast tego pojawi się ciąg "Użytkownik zalogowany z $ ip".
mogę to zrobić:
# 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;
I uzyskać następujące wyniki:
user_id | name
---------+------------------------------
1 | Elise
2 | John
3 | User logged in from 10.0.0.9
co jest dobre. Ale nie mogę wymyślić, jak manipulować tymi danymi w formacie JSON, jak pierwszy przykład.
Pożądany wynik jest oczywiście następuje:
[{"user_id":1,"name":"Elise"},{"user_id":2,"name":"John"},{"user_id":3,"name":"User logged in from 10.0.0.9"}]
Następujące nie działa:
# 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
nie mogę dowiedzieć się, w dowolny sposób, aby uzyskać dane do formatu array_agg akceptuje. Próbowałem nawet utworzyć niestandardowy typ, który pasował do formatu temp_user i próbował wywoływać array_agg do konstruktora typu, który zwrócił ten sam błąd. Błąd nie ma dla mnie sensu - jeśli podzapytanie jest zagregowane, to nie powinno mieć znaczenia, czy zwraca więcej niż jedną kolumnę. Jakakolwiek rada?
Potwierdzam, że to działa; Właśnie zastosowałem tę metodę pomyślnie do mojego prawdziwego zapytania. Dzięki! – hs0
Zapytanie można nieco uprościć, zastępując 'array_agg (wiersz (t. *))' Po prostu 'array_agg (t)'. W ten sposób zachowujesz również nazwy kolumn z podzapytania. –