sql >> Databáze >  >> RDS >> PostgreSQL

PostgreSQL vrátí výsledek jako pole JSON?

TL;DR

SELECT json_agg(t) FROM t

pro pole objektů JSON a

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

pro objekt JSON z polí.

Seznam objektů

Tato část popisuje, jak vygenerovat pole JSON objektů, přičemž každý řádek se převede na jeden objekt. Výsledek vypadá takto:

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

9.3 a vyšší

json_agg funkce vytváří tento výsledek ihned po vybalení. Automaticky zjistí, jak převést svůj vstup na JSON, a agreguje ho do pole.

SELECT json_agg(t) FROM t

Neexistuje žádný jsonb (zavedené v 9.4) verzi json_agg . Řádky můžete buď agregovat do pole a poté je převést:

SELECT to_jsonb(array_agg(t)) FROM t

nebo zkombinujte json_agg s obsazením:

SELECT json_agg(t)::jsonb FROM t

Moje testování naznačuje, že nejprve je agregovat do pole je trochu rychlejší. Mám podezření, že je to proto, že obsazení musí analyzovat celý výsledek JSON.

9.2

9.2 nemá json_agg nebo to_json funkce, takže musíte použít starší array_to_json :

SELECT array_to_json(array_agg(t)) FROM t

Volitelně můžete zahrnout row_to_json zavolejte v dotazu:

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

To převede každý řádek na objekt JSON, agreguje objekty JSON jako pole a poté pole převede na pole JSON.

Nebyl jsem schopen rozeznat žádný významný rozdíl ve výkonu mezi těmito dvěma.

Objekt seznamů

Tato část popisuje, jak vygenerovat objekt JSON, přičemž každý klíč je sloupec v tabulce a každá hodnota je polem hodnot sloupce. Výsledek vypadá takto:

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

9,5 a vyšší

Můžeme využít json_build_object funkce:

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

Můžete také agregovat sloupce, vytvořit jeden řádek a ten pak převést na objekt:

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

Všimněte si, že alias polí je absolutně nezbytný k zajištění toho, že objekt má požadovaná jména.

Která je jasnější, je věcí názoru. Pokud používáte json_build_object Velmi doporučuji umístit jeden pár klíč/hodnota na řádek, aby se zlepšila čitelnost.

Můžete také použít array_agg místo json_agg , ale mé testování ukazuje, že json_agg je o něco rychlejší.

Neexistuje žádný jsonb verzi json_build_object funkce. Můžete agregovat do jednoho řádku a převést:

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

Na rozdíl od ostatních dotazů pro tento druh výsledku array_agg se zdá být trochu rychlejší při použití to_jsonb . Mám podezření, že je to způsobeno režijní analýzou a ověřováním výsledku JSON json_agg .

Nebo můžete použít explicitní obsazení:

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

to_jsonb verze vám umožňuje vyhnout se obsazení a je rychlejší, podle mého testování; znovu se domnívám, že je to kvůli režii analýzy a ověřování výsledku.

9.4 a 9.3

json_build_object funkce byla ve verzi 9.5 nová, takže v předchozích verzích musíte agregovat a převést na objekt:

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

nebo

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

podle toho, zda chcete json nebo jsonb .

(9.3 nemá jsonb .)

9.2

Ve verzi 9.2 dokonce ani to_json existuje. Musíte použít 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

Dokumentace

Najděte dokumentaci pro funkce JSON ve funkcích JSON.

json_agg je na stránce souhrnných funkcí.

Design

Pokud je důležitý výkon, ujistěte se, že srovnáváte své dotazy se svým vlastním schématem a daty, spíše než důvěřujte mému testování.

Zda je to dobrý design nebo ne, opravdu záleží na vaší konkrétní aplikaci. Co se týče udržovatelnosti, nevidím žádný zvláštní problém. Zjednodušuje kód vaší aplikace a znamená, že v této části aplikace je potřeba méně údržby. Pokud vám PG může po vybalení poskytnout přesně ten výsledek, který potřebujete, jediný důvod, proč jej nepoužít, mě napadá, jsou úvahy o výkonu. Neobjevujte znovu kolo a všechno.

Nulové

Agregační funkce obvykle vrátí NULL když pracují přes nula řádků. Pokud je to možné, možná budete chtít použít COALESCE abychom se jim vyhnuli. Pár příkladů:

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

Nebo

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

Poděkování Hannesu Landeholmovi za to, že na to upozornil



  1. Jak obnovit materializovaný pohled v orákulu

  2. Jak importovat databázi pomocí příkazového řádku

  3. Rady k výkonu SQL Server od Brenta Ozara a Pinala Davea

  4. INSTR() Ekvivalent v SQL Server