PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

PostgreSQL zwraca zestaw wyników jako tablicę JSON?

TL;DR

SELECT json_agg(t) FROM t

dla tablicy obiektów JSON i

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )
FROM t

dla obiektu JSON tablic.

Lista obiektów

W tej sekcji opisano sposób generowania tablicy obiektów JSON, w której każdy wiersz jest konwertowany na pojedynczy obiekt. Wynik wygląda tak:

[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]

9.3 i nowsze

json_agg funkcja generuje ten wynik po wyjęciu z pudełka. Automatycznie dowiaduje się, jak przekonwertować dane wejściowe do formatu JSON i agregować je w tablicę.

SELECT json_agg(t) FROM t

Nie ma jsonb (wprowadzony w 9.4) wersja json_agg . Możesz albo zagregować wiersze w tablicę, a następnie je przekonwertować:

SELECT to_jsonb(array_agg(t)) FROM t

lub połącz json_agg z obsadą:

SELECT json_agg(t)::jsonb FROM t

Moje testy sugerują, że agregowanie ich najpierw w tablicę jest nieco szybsze. Podejrzewam, że dzieje się tak, ponieważ obsada musi przeanalizować cały wynik JSON.

9,2

9.2 nie ma json_agg lub to_json funkcje, więc musisz użyć starszego array_to_json :

SELECT array_to_json(array_agg(t)) FROM t

Opcjonalnie możesz dołączyć row_to_json zadzwoń w zapytaniu:

SELECT array_to_json(array_agg(row_to_json(t))) FROM t

To konwertuje każdy wiersz na obiekt JSON, agreguje obiekty JSON jako tablicę, a następnie konwertuje tablicę na tablicę JSON.

Nie byłem w stanie dostrzec żadnej znaczącej różnicy w wydajności między tymi dwoma.

Obiekt list

W tej sekcji opisano, jak wygenerować obiekt JSON, przy czym każdy klucz jest kolumną w tabeli, a każda wartość jest tablicą wartości kolumny. Wynik wygląda tak:

{"a":[1,2,3], "b":["value1","value2","value3"]}

9,5 i więcej

Możemy wykorzystać json_build_object funkcja:

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )
FROM t

Możesz także zagregować kolumny, tworząc pojedynczy wiersz, a następnie przekonwertować go na obiekt:

SELECT to_json(r)
FROM (
    SELECT
        json_agg(t.a) AS a,
        json_agg(t.b) AS b
    FROM t
) r

Zwróć uwagę, że aliasowanie tablic jest absolutnie wymagane, aby zapewnić, że obiekt ma żądane nazwy.

To, które z nich jest jaśniejsze, jest kwestią opinii. Jeśli używasz json_build_object funkcji, gorąco polecam umieszczenie jednej pary klucz/wartość w linii, aby poprawić czytelność.

Możesz także użyć array_agg zamiast json_agg , ale moje testy wskazują, że json_agg jest nieco szybszy.

Nie ma jsonb wersja json_build_object funkcjonować. Możesz zagregować w jeden wiersz i przekonwertować:

SELECT to_jsonb(r)
FROM (
    SELECT
        array_agg(t.a) AS a,
        array_agg(t.b) AS b
    FROM t
) r

W przeciwieństwie do innych zapytań o tego rodzaju wynik, array_agg wydaje się być trochę szybszy przy użyciu to_jsonb . Podejrzewam, że jest to spowodowane narzutem analizowania i weryfikowania wyniku JSON json_agg .

Możesz też użyć wyraźnej obsady:

SELECT
    json_build_object(
        'a', json_agg(t.a),
        'b', json_agg(t.b)
    )::jsonb
FROM t

to_jsonb wersja pozwala uniknąć rzutów i jest szybsza, według moich testów; ponownie, podejrzewam, że jest to spowodowane narzutem na analizę i walidację wyniku.

9.4 i 9.3

json_build_object funkcja była nowa w 9.5, więc musisz agregować i konwertować do obiektu w poprzednich wersjach:

SELECT to_json(r)
FROM (
    SELECT
        json_agg(t.a) AS a,
        json_agg(t.b) AS b
    FROM t
) r

lub

SELECT to_jsonb(r)
FROM (
    SELECT
        array_agg(t.a) AS a,
        array_agg(t.b) AS b
    FROM t
) r

w zależności od tego, czy chcesz json lub jsonb .

(9.3 nie ma jsonb .)

9,2

W wersji 9.2 nawet to_json istnieje. Musisz użyć row_to_json :

SELECT row_to_json(r)
FROM (
    SELECT
        array_agg(t.a) AS a,
        array_agg(t.b) AS b
    FROM t
) r

Dokumentacja

Znajdź dokumentację funkcji JSON w funkcjach JSON.

json_agg znajduje się na stronie funkcji agregujących.

Projekt

Jeśli wydajność jest ważna, upewnij się, że porównałeś swoje zapytania z własnym schematem i danymi, zamiast ufać moim testom.

To, czy projekt jest dobry, czy nie, zależy od konkretnego zastosowania. Jeśli chodzi o łatwość utrzymania, nie widzę żadnego szczególnego problemu. Upraszcza to kod aplikacji i oznacza, że ​​w tej części aplikacji jest mniej do utrzymania. Jeśli PG może dać ci dokładnie taki wynik, jakiego potrzebujesz po wyjęciu z pudełka, jedynym powodem, dla którego mogę go nie używać, są względy wydajności. Nie wymyślaj koła na nowo i w ogóle.

Null

Funkcje agregujące zazwyczaj zwracają NULL kiedy operują na zerowych rzędach. Jeśli jest taka możliwość, możesz użyć COALESCE aby ich uniknąć. Kilka przykładów:

SELECT COALESCE(json_agg(t), '[]'::json) FROM t

Lub

SELECT to_jsonb(COALESCE(array_agg(t), ARRAY[]::t[])) FROM t

Podziękowanie dla Hannesa Landeholma za wskazanie tego



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak działa make_interval() w PostgreSQL

  2. Sposoby dostępu do bazy danych Oracle w PostgreSQL

  3. Zaawansowane dopasowywanie partycji do łączenia partycji

  4. Zarządzanie wysoką dostępnością w PostgreSQL – Część II:Menedżer replikacji

  5. Jak zwrócić tablicę jsonb i tablicę obiektów z moich danych?