【问题标题】:ARRAY_AGG interrupted by GROUP BY when trying to ORDER BY timestamps尝试 ORDER BY 时间戳时,ARRAY_AGG 被 GROUP BY 中断
【发布时间】:2018-01-02 10:38:09
【问题描述】:

我已经为我的问题准备了SQL Fiddle -

给定下表:

CREATE TABLE chat(
    gid integer,            /* game id */
    uid integer,            /* user id */
    created timestamptz,
    msg text
);

填入如下测试数据:

INSERT INTO chat(gid, uid, created, msg) VALUES
    (10, 1, NOW() + interval '1 min', 'msg 1'),
    (10, 2, NOW() + interval '2 min', 'msg 2'),
    (10, 1, NOW() + interval '3 min', 'msg 3'),
    (10, 2, NOW() + interval '4 min', 'msg 4'),
    (10, 1, NOW() + interval '5 min', 'msg 5'),
    (10, 2, NOW() + interval '6 min', 'msg 6'),
    (20, 3, NOW() + interval '7 min', 'msg 7'),
    (20, 4, NOW() + interval '8 min', 'msg 8'),
    (20, 4, NOW() + interval '9 min', 'msg 9');

我可以使用以下查询:

SELECT json_object_agg(
          gid, array_to_json(y)
       ) FROM (
       SELECT  gid,
          array_agg(
            json_build_object(
              'uid', uid,
              'created', EXTRACT(EPOCH FROM created)::int,
              'msg', msg)
          ) y
        FROM  chat 
        GROUP BY gid /*, created
        ORDER BY created ASC */
) x;

用于以“gid”作为键和数组值的 JSON 对象获取表记录:

{ "20" : [
    {"uid" : 3, "created" : 1514889490, "msg" : "msg 7"},
    {"uid" : 4, "created" : 1514889550, "msg" : "msg 8"},
    {"uid" : 4, "created" : 1514889610, "msg" : "msg 9"}
], 

"10" : [
    {"uid" : 1, "created" : 1514889130, "msg" : "msg 1"},
    {"uid" : 2, "created" : 1514889190, "msg" : "msg 2"},
    {"uid" : 1, "created" : 1514889250, "msg" : "msg 3"},
    {"uid" : 2, "created" : 1514889310, "msg" : "msg 4"},
    {"uid" : 1, "created" : 1514889370, "msg" : "msg 5"},
    {"uid" : 2, "created" : 1514889430, "msg" : "msg 6"}
] }

但是我错过了一件小事,只是想不通:

我需要通过“created”对数组进行排序。

所以我在上面的查询中添加了ORDER BY created ASC,还必须添加GROUP BY gid, created(您可以看到上面查询中注释掉的有问题的代码)。

打破但是 array_agg 并导致 1 元素数组(并覆盖重复的“gid”键,当从我的自定义存储函数返回为 jsonb 时):

{ "10": [{ "uid":2, "created":1514889800, "msg":"msg 6" }],

  "20": [{ "uid":4, "created":1514889980, "msg":"msg 9" }] }

在这里甚至可以订购还是我应该求助于在我的 JAVA 应用程序中订购?

【问题讨论】:

    标签: sql postgresql sql-order-by postgresql-json array-agg


    【解决方案1】:

    array_agg 调用中指定ORDER BY

    SELECT json_object_agg(gid, array_to_json(y))
    FROM (
      SELECT  gid,
        array_agg(
          json_build_object(
            'uid', uid,
            'created', EXTRACT(EPOCH FROM created)::int,
            'msg', msg
          ) ORDER BY created -- Order the elements in the resulting array
        ) AS y
      FROM chat 
      GROUP BY gid
    ) x;
    

    返回(使用jq 格式化):

    {
      "10": [
        {
          "uid": 1,
          "created": 1514890093,
          "msg": "msg 1"
        },
        {
          "uid": 2,
          "created": 1514890153,
          "msg": "msg 2"
        },
        {
          "uid": 1,
          "created": 1514890213,
          "msg": "msg 3"
        },
        {
          "uid": 2,
          "created": 1514890273,
          "msg": "msg 4"
        },
        {
          "uid": 1,
          "created": 1514890333,
          "msg": "msg 5"
        },
        {
          "uid": 2,
          "created": 1514890393,
          "msg": "msg 6"
        }
      ],
      "20": [
        {
          "uid": 3,
          "created": 1514890453,
          "msg": "msg 7"
        },
        {
          "uid": 4,
          "created": 1514890513,
          "msg": "msg 8"
        },
        {
          "uid": 4,
          "created": 1514890573,
          "msg": "msg 9"
        }
      ]
    }
    

    【讨论】:

    • 没想到ORDER BY可以和聚合函数一起使用,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2019-10-21
    • 1970-01-01
    相关资源
    最近更新 更多