2017-02-26 6 views
1
でARRAY_AGG

次のように私は、クエリを持っている:GROUP BYおよび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) 

をし、それのように結果を返します:私は実際に私は結果がとてもid列によってグループ化することにしたい

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

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 

これは、正しい結果が得られます:「いくつかの試行錯誤の後、このSQLを生成しまし

id | _rowId | name 
1 |{1}  | A 
2 |{2}  | C 
3 |{1,2} | B 

これはかなりうまくいき、うまくいくようですが、このクエリをより良い方法で構築する方法がないのではないかと思いますか?

+2

これは自然で適切な方法で行っています。 'LEFT JOIN ... ON TRUE'は少し奇妙に見えますが、' CROSS JOIN'だけが読みやすくなります。 – klin

+0

ありがとう@klin - 私はCROSS JOINの可読性がより良く、それに応じて私のクエリを適合させました。 – Jarym

+0

引用符で囲まれた識別子は読みにくく、問題を引き起こす可能性があります。識別子に不正な文字が含まれている場合にのみ使用してください。基本的にORMだけがそれを必要とします。 –

答えて

1

いくつかのマイナーな点:あなたは、json_to_recordset()あなたが効果的に修飾されていない2つの行ソース間の結合行うが、行の間の結合されていない行ソース"data"と機能との間に加わる横暗黙を行っているので

  • "data"から、関数が生成する行のいずれかです。 CROSS JOIN句は、修飾されていない結合を意味し、これが横結合であるという事実を隠しています(LEFT節が削除された場合は元のバージョンがより好きでした)。このような場合、私は単に良いol 'カンマ,リスト:FROM "data", json_to_recordset("data"."habitas")を使用します。
  • 一貫して識別子の前後に二重引用符"を使用する必要があります。
  • "_rowId"の値が配列内で順番になるようにしたい場合は、array_agg("data"."_rowId" ORDER BY "data"."_rowId")を使用してください。
+0

ありがとうございました。私のオリジナルのソリューションが見つかったのです。私はそれをFROM句に追加することはできません。それは非常にクールです!一貫した見積もりに同意し、注文能力は手ごわいです。もう一度ありがとうございます。 – Jarym