2017-02-26 9 views
1

Ich habe eine Abfrage wie folgt:GROUP BY und array_agg in Postgres

WITH "data" ("displayName","habitas","_rowId") AS (VALUES 
('Moo','[{"id":"1", "name": "A"},{"id":"2", "name": "B"}]'::json,1) 
,('Boo','[{"id":"3", "name": "C"},{"id":"2", "name": "B"}]'::json,2)) 
SELECT 
    t.id, "data"."_rowId", t.name 
FROM "data" 
    CROSS JOIN 
    json_to_recordset("data"."habitas") as t("id" text, "name" text) 

und es gibt Ergebnisse als:

id | _rowId | name 
1 |1  | A 
2 |1  | B 
3 |2  | C 
2 |2  | B 

Ich möchte eigentlich die Ergebnisse durch die id-Spalte gruppiert werden, damit ich habe diese SQL nach einiger Versuch und Fehler erzeugt hat:

WITH "data" ("displayName","habitas","_rowId") AS (VALUES 
('Moo','[{"id":"1", "name": "A"},{"id":"2", "name": "B"}]'::json,1) 
,('Boo','[{"id":"3", "name": "C"},{"id":"2", "name": "B"}]'::json,2)) 
SELECT 
    t.id, array_agg("data"."_rowId"), t.name 
FROM "data" 
    CROSS JOIN 
    json_to_recordset("data"."habitas") as t("id" text, "name" text) 
GROUP BY t.id, t.name 

und dies erzeugt dann die richtigen Ergebnisse:

Es ist ziemlich ok und scheint zu arbeiten, aber ich frage mich, ob ich irgendwelche Tricks verpasst habe, um diese Abfrage besser zu konstruieren?

+2

Sie haben es in einer natürlichen, richtigen Weise getan. 'LEFT JOIN ... ON TRUE' sieht etwas komisch aus, nur' CROSS JOIN' ist lesbarer. – klin

+0

Danke @klin - mir gefällt auch die Lesbarkeit von CROSS JOIN besser so habe meine Suchanfrage entsprechend angepasst. – Jarym

+0

Zitierte Bezeichner sind schwer zu lesen und können Probleme verursachen. Verwenden Sie es nur, wenn die Bezeichner ungültige Zeichen enthalten. Grundsätzlich werden nur ORMs benötigt. –

Antwort

1

Einige kleinere Punkte:

  • Da man eine implizite ausführen zwischen der Zeilenquelle "data" und der Funktion kommen seitliche json_to_recordset() Sie sind zwischen einer Reihe effektiv kein unqualifizierte Verbindung zwischen zwei Zeilenquellen machen, sondern eine Join von "data" und welche Reihen die Funktion erzeugt. Die CROSS JOIN-Klausel impliziert einen unqualifizierten Join und verdeckt die Tatsache, dass es sich um einen lateralen Join handelt (daher mochte ich Ihre ursprüngliche Version besser, wenn die LEFT-Klausel entfernt wird). In einem Fall wie diesem würde ich einfach das gute alte Komma , Liste verwenden: FROM "data", json_to_recordset("data"."habitas").
  • Sie sollten doppelte Anführungszeichen " konsistent um Identifikatoren verwenden.
  • Wenn Sie sicherstellen möchten, dass die "_rowId" Werte im Array in Ordnung sind, sollten Sie array_agg("data"."_rowId" ORDER BY "data"."_rowId") verwenden.
+0

Danke, ja, so habe ich meine ursprüngliche Lösung gefunden. Ich wusste nicht, dass ich es einfach in die FROM-Klausel einfügen kann, das ist SEHR cool! Sich auf ein konsistentes Angebot zu einigen und die Bestellmöglichkeit ist verdammt praktisch - nochmals vielen Dank. – Jarym