Leider gibt es in der SQL-Syntax keine Bestimmung, die besagt, dass "alle Spalten außer dieser einen Spalte" . Sie können Ihr Ziel erreichen, indem Sie die verbleibende Liste der Spalten in einem Ausdruck vom Zeilentyp ausschreiben :
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Das ist die Abkürzung für die explizitere Form: . ROW
(b.col1, b.col2, b.col3)
Allerdings Spaltennamen sind nicht in Reihe-Typ Ausdrücke erhalten. Auf diese Weise erhalten Sie generische Schlüsselnamen im JSON-Objekt. Ich sehe 3 Optionen, um die ursprünglichen Spaltennamen beizubehalten:
1. Auf registrierten Typ umwandeln
Umwandlung in einen bekannten (registrierten) Zeilentyp. Ein Typ wird für jede vorhandene Tabelle oder Sicht oder mit einer expliziten CREATE TYPE
Anweisung registriert . Sie können eine temporäre Tabelle für eine Ad-hoc-Lösung verwenden (gültig für die Dauer der Sitzung):
CREATE TEMP TABLE x (col1 int, col2 text, col3 date); -- use adequate data types!
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)::x) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
2. Verwenden Sie eine Unterauswahl
Verwenden Sie eine Unterauswahl, um eine abgeleitete Tabelle zu erstellen und auf die gesamte Tabelle zu verweisen . Dies trägt auch Spaltennamen. Es ist ausführlicher, aber Sie benötigen keinen registrierten Typ:
SELECT a.id, a.name
, json_agg((SELECT x FROM (SELECT b.col1, b.col2, b.col3) AS x)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
SELECT a.id, a.name
, json_agg(json_build_object('col1', b.col1, 'col2', b.col2, 'col3', b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Verbunden:
Ähnliches gilt für jsonb
die jeweiligen Funktionen jsonb_agg()
und jsonb_build_object()
.
Für Postgres 9.5 oder später auch sehen a_horse Antwort mit einer neuen kürzerer Syntaxvariante: Postgres hinzugefügt , um den Minus-Operator -
fürjsonb
sagen „alle Tasten außer diesen einem Schlüssel“ .
Da Postgres 10 "außer mehreren Schlüsseln" mit dem gleichen Operator implementiert ist, wird text[]
als 2. Operand - wie mlt - kommentiert.
Ab 9.6 können Sie einfach
-
einen Schlüssel aus einem JSONB entfernen:to_jsonb(b)
konvertiert die gesamte Zeile und entfernt- 'item_id'
dann den Schlüssel mit dem Namen,item_id
dessen Ergebnis dann aggregiert wird.quelle
json_agg
Funktion:function json_agg(record) does not exist
Sie können dies mithilfe von Unterabfragen auch ohne Gruppierung durchführen
kehrt zurück
Dieser Artikel von John Atten ist wirklich interessant und hat mehr Details
quelle
Ich habe festgestellt, dass es am besten ist, den JSON zu erstellen und dann zu aggregieren. z.B
Beachten Sie, dass dies als Unterabfrage durchgeführt werden kann, wenn Sie CTEs nicht mögen (oder Leistungsprobleme haben, weil Sie sie verwenden).
Beachten Sie auch, dass es von Vorteil sein kann, eine Funktion zu erstellen, die die Schlüssel-Wert-Paare für Sie umschließt, damit der Code übersichtlicher aussieht. Sie würden Ihre Funktion (zum Beispiel) übergeben
'ecks', 'x'
und es würde zurückkehren"ecks": "x"
.quelle
Es gibt zwar immer noch keine Möglichkeit, die Auswahl aller Spalten bis auf ein Bit zu
json_agg(to_json(b.col_1, b.col_2, b.col_3 ...))
ändern , aber Sie können damit ein JSON-Array von JSONs im Format abrufen{"col_1":"col_1 value", ...}
.Die Abfrage würde also ungefähr so aussehen:
und würde Zeilen zurückgeben als:
(Ich bin jetzt auf Postgres 9.5.3 und nicht 100% sicher, wann diese Unterstützung hinzugefügt wurde.)
quelle
Sie können verwendet werden,
json_build_object
wie diesquelle