Postgres中的GROUP BY和array_agg

时间:2017-02-26 16:15:09

标签: postgresql

我的查询如下:

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列分组,因此我在经过一些试验和错误后生成了这个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

看起来相当不错并且似乎有效但我想知道我是否错过了以更好的方式构建此查询的任何技巧?

1 个答案:

答案 0 :(得分:1)

一些小问题:

  • 由于您在行源CustomJS和函数"data"之间执行隐式横向连接,因此您实际上没有在两个行源之间进行非限定连接,而是在{{1和函数生成的任何行。 json_to_recordset()子句意味着一个不合格的连接,它掩盖了这是一个横向连接的事实(所以如果删除了"data"子句,我更喜欢你的原始版本)。在这种情况下,我会简单地使用好的'逗号CROSS JOIN列表:LEFT
  • 您应该在标识符周围使用双引号,
  • 如果您想保证数组中FROM "data", json_to_recordset("data"."habitas")值的顺序排列,那么您应该使用"