ARRAY_AGG 在尝试 ORDER BY 时间戳时被 GROUP BY 打断
ARRAY_AGG interrupted by GROUP BY when trying to ORDER BY timestamps
我已经为我的问题准备了SQL Fiddle -
鉴于以下 table:
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;
用于获取 table 记录作为 JSON 对象,使用 "gid" 作为键和数组值:
{ "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 应用程序中进行订购?
在 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;
returns(使用 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"
}
]
}
我已经为我的问题准备了SQL Fiddle -
鉴于以下 table:
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;
用于获取 table 记录作为 JSON 对象,使用 "gid" 作为键和数组值:
{ "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 应用程序中进行订购?
在 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;
returns(使用 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"
}
]
}