2017-02-26 63 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 | _rowId | name 
1 |1  | A 
2 |1  | B 
3 |2  | C 
2 |2  | B 

其實我想要的結果由ID列進行分組,所以我「VE產生了一些試驗和錯誤之後此SQL:

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 

並且這然後產生正確的結果:

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

幾個小點:

  • 既然你執行的是隱行來源"data"和功能之間的橫向連接json_to_recordset()你實際上沒有做兩個行源之間的不合格的加入,但一排之間的連接從"data"和函數產生的任何行。 CROSS JOIN條款意味着一個不合格的連接,它掩蓋了這樣一個事實,即這是一個橫向連接(所以如果LEFT子句被刪除,我更喜歡你的原始版本)。在這樣的情況下,我會簡單地使用好的醇'逗號,列表:FROM "data", json_to_recordset("data"."habitas")
  • 您應該圍繞標識符一致地使用雙引號"
  • 如果你想保證"_rowId"值在數組中是有序的,那麼你應該使用array_agg("data"."_rowId" ORDER BY "data"."_rowId")
+0

謝謝,是的,這就是我找到我原來的解決方案。我沒有意識到我可以將它添加到FROM子句中,這非常酷!同意一致的引用和訂購能力是該死的方便 - 再次感謝你。 – Jarym