Niestety w składni SQL nie ma przepisu mówiącego „wszystkie kolumny oprócz tej jednej kolumny” . Możesz osiągnąć swój cel, wypisując pozostałą listę kolumn w wyrażeniu typu wiersz :
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;
To skrót od bardziej zrozumiałej formie: . ROW
(b.col1, b.col2, b.col3)
Jednak nazwy kolumn nie są zachowywane w wyrażeniach typu wierszowego. W ten sposób otrzymujesz ogólne nazwy kluczy w obiekcie JSON. Widzę 3 opcje zachowania oryginalnych nazw kolumn:
1. Przesyłaj do zarejestrowanego typu
Rzuć na dobrze znany (zarejestrowany) typ wiersza. Typ jest rejestrowany dla każdej istniejącej tabeli lub widoku lub z wyraźną CREATE TYPE
instrukcją. Możesz użyć tabeli tymczasowej dla rozwiązania ad-hoc (obowiązuje przez czas trwania sesji):
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. Użyj podselekcji
Użyj podselekcji, aby zbudować tabelę pochodną i odwołać się do tabeli jako całości . To także przenosi nazwy kolumn. Jest bardziej szczegółowy, ale nie potrzebujesz zarejestrowanego typu:
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;
Związane z:
Podobnie w jsonb
przypadku odpowiednich funkcji jsonb_agg()
i jsonb_build_object()
.
Dla PostgreSQL 9.5 lub nowszy również zobaczyć odpowiedź a_horse w nowym wariancie krótszy składni: Postgres dodał operator minus -
zajsonb
powiedzieć „wszystkie klawisze z wyjątkiem tego jednego klucza” .
Ponieważ Postgres 10 „oprócz kilku kluczy” jest implementowany z tym samym operatorem, który bierze text[]
jako drugi operand - jak komentuje mlt.
Począwszy od wersji 9.6, możesz po prostu użyć
-
do usunięcia klucza z JSONB:to_jsonb(b)
przekształci cały wiersz, a- 'item_id'
następnie usunie klucz o nazwie,item_id
której wynik zostanie następnie zagregowany.źródło
json_agg
funkcją:function json_agg(record) does not exist
Możesz to zrobić bez grupowania za pomocą podkwerend
zwroty
Ten artykuł od Johna Attena jest naprawdę interesujący i zawiera więcej szczegółów
źródło
Przekonałem się, że najlepiej jest utworzyć JSON, a następnie go zagregować. na przykład
Uwaga: można to zrobić jako podzapytanie, jeśli nie lubisz CTE (lub masz problemy z wydajnością z powodu korzystania z niego).
Zauważ też, że jeśli będziesz często to robić, może być korzystne utworzenie funkcji do zawijania dla Ciebie par klucz-wartość, aby kod wyglądał na czystszy. Przekazałeś swoją funkcję (na przykład)
'ecks', 'x'
i ona powróciłaby"ecks": "x"
.źródło
Chociaż nadal nie ma sposobu, aby zrobić nic z zaznaczeniem wszystkich kolumn oprócz jednego bitu, ale możesz użyć,
json_agg(to_json(b.col_1, b.col_2, b.col_3 ...))
aby uzyskać tablicę jsonów jsonów w formacie{"col_1":"col_1 value", ...}
.Tak więc zapytanie wyglądałoby mniej więcej tak:
i zwraca wiersze jako:
(Jestem teraz na Postgres 9.5.3 i nie jestem w 100% pewien, kiedy ta obsługa została dodana).
źródło
Możesz użyć w
json_build_object
ten sposóbźródło