【问题标题】:Aggregating rows into JSON hash将行聚合为 JSON 哈希
【发布时间】:2013-04-19 22:36:03
【问题描述】:

我有下表:

roles

id |  name | person
---+-------+--------
1  | admin | jon
2  | admin | fred
3  | user  | alfred
4  | user  | jon

其中名称可以变化为任何值。

我想得到一个像这样的 JSON 哈希:

{"admin": ["jon", "fred"], "user": ["alfred", "jon"]}

使用 PL/PGSQL

【问题讨论】:

    标签: postgresql plpgsql postgresql-9.2


    【解决方案1】:

    我会假设名称可能会有所不同,因为没有它就没有挑战。 使用eval function:

    CREATE OR REPLACE FUNCTION eval(expression text) RETURNS text
    AS
    $body$
    DECLARE
      result text;
    BEGIN
      execute expression INTO RESULT;
      RETURN result;
    END;
    $body$
    language plpgsql
    

    我们可以创建一个动态交叉表:

    SELECT eval('SELECT row_to_json(q)
    FROM (SELECT '||(SELECT string_agg(DISTINCT '"'||name||'"',',')
                     FROM roles)||'
          FROM crosstab(''SELECT 1,name,array_agg(person)::text[]
                          FROM roles
                          GROUP BY name;
                        '') as ct(row_name int,'||(SELECT string_agg(DISTINCT '"'||name||'"                   text[]',',')
    FROM roles)||')
    )as q');
    

    编辑

    不那么花哨的方法:

    SELECT '{'||string_agg(temp,',')||'}'
    FROM
    (
    SELECT '"'||name||'": ['||(string_agg(person,',')::text)||']' as temp FROM roles GROUP BY name
    ) as q
    

    【讨论】:

    • 这是一个有趣的方法,我会看看我能用它做什么。
    • 我试过你的方法,它有效,但性能很糟糕。我目前正在研究一种提高应用程序性能的方法(JSON 生成现在在 ruby​​ 中),我应该提到性能要求。我仍然会接受你的回答,因为它确实回答了我的问题。
    • @NicolasGoy 我想我可能对那个交叉表有点忘乎所以。我现在添加的查询应该会执行得更好。
    • 我会看看 9.3 的建议,但你的解决方案现在仍然有效。
    【解决方案2】:

    postgres 的当前开发版本(未来 9.3)将重点关注数据库内部的 JSON 支持。根据您需要解决此问题的速度有多快,您可以等待 9.3 或安装当前的测试版(其中应该包含新功能)。

    这里有两篇关于新的 json 特性的文章 - 第一篇是第三方的 - 第二篇是开发树上的 JSON 库参考:

    【讨论】:

      猜你喜欢
      • 2012-02-26
      • 1970-01-01
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-22
      • 2017-12-06
      • 2011-02-25
      相关资源
      最近更新 更多