我对此查询的目标是从communities
表中提取所有内容,以及从array_agg
jsonb
个select communities.*,
(
select array_agg(jsonb_build_object('id', community_permissions.document_id))
from documents as conversations
join community_permissions on community_permissions.document_id = conversations.id
where conversations.published = true
and community_permissions.community_id = communities.id
) as conversations
from communities where communities.id = 110;
个对象中提取所有内容。这样就可以在未分类的情况下正常工作:
communities
这将为[{ id: 1 }, { id: 2 } ...]
中的列返回一个包含普通列的行,并在conversations
列中返回一个类似select communities.*,
(
select array_agg(jsonb_build_object('id', community_permissions.document_id))
from documents as conversations
join community_permissions on community_permissions.document_id = conversations.id
where conversations.published = true
and community_permissions.community_id = communities.id
order by conversations.updated_at desc
) as conversations
from communities where communities.id = 110;
的json数组。一切都很好,查询工作得很好,我可以在SQL中声明性地获取一行及其重要的关系。我甚至可以从另一个表中过滤连接的返回值(在此列表中只返回已发布的对话)。
我现在要做的是根据文档表中的属性对对话进行排序(别名为上面的对话)。天真的方法:
select communities.*,
(
select array_agg(jsonb_build_object('id', community_permissions.document_id))
from documents as conversations
join community_permissions on community_permissions.document_id = conversations.id
where conversations.published = true
and community_permissions.community_id = communities.id
group by conversations.updated_at
order by conversations.updated_at desc
) as conversations
from communities where communities.id = 110;
不起作用 - 列walker希望conversations.updated_at值在group_by子句中。如果我像这样添加group by子句:
limit 1
看起来array_agg实际上不再聚合响应 - 我得到一个错误“由用作表达式的子查询返回的多行”。我可以在order by
之后放置一个with q1 as (
select conversations.id as id, community_permissions.community_id as community_id
from documents as conversations
join community_permissions on community_permissions.document_id = conversations.id
where conversations.published = true order by conversations.updated_at desc
)
select communities.id, (
select array_agg(jsonb_build_object('id', q1.id))) as conversations
from communities join q1 on q1.community_id = communities.id
where communities.id = 110
group by communities.id;
,然后执行查询,但之后我只在array_agg列中进行一次会话 - 至少是最近一次。所以看起来array_agg实际上并没有进入数组,可以这么说。
我可以通过将整个事物分开并使用CTE来执行此查询:
rowSums
但这非常低效,解释器表明它在每次查询运行时对整个会话表进行排序,并且任何给定的社区只有一小部分会话表通过community_permissions与之共享。
这也令人不满意,因为我正在尝试模块化我的查询,以便后端可以决定,“嘿,你将需要这些值”并将它们推送到SQL查询中并在一个查询中一次完成所有操作而不是拉动社区,然后手动查询每个关系(通常不止一个 - 社区有成员,对话,粉丝等)。最糟糕的情况是,我可以这样做 - 只需处理后端节点层中的额外提取并在那里进行组装,但将其全部放在子查询中似乎更优雅(直到我需要这种排序功能)。
答案 0 :(得分:2)
其中一个“在stackoverflow上写了一篇很长的帖子并在十分钟后找到答案”的情况。
为了将来参考,诀窍是我把订单放在了错误的地方。这有效:
select communities.*,
(
select array_agg(jsonb_build_object('id', community_permissions.document_id) order by conversations.updated_at desc)
from documents as conversations
join community_permissions on community_permissions.document_id = conversations.id
where conversations.published = true
and community_permissions.community_id = communities.id
) as conversations
from communities where communities.id = 110;
请注意,order by
现在位于array_agg
调用中,而不是在子查询内。
答案 1 :(得分:2)
您可以在聚合函数中指定顺序。
尝试:
select communities.*,
(
select array_agg(jsonb_build_object('id', community_permissions.document_id) order by conversations.updated_at desc)
from documents as conversations
join community_permissions on community_permissions.document_id = conversations.id
where conversations.published = true
and community_permissions.community_id = communities.id
) as conversations
from communities where communities.id = 110;