如何用单条MySQL查询获取嵌套JSON格式的事件关联用户数据
解决MySQL单查询生成嵌套JSON的问题
嘿,我完全懂你碰到的麻烦——普通关联查询会把每个用户和事件的对应关系拆成单独记录,没法直接得到你想要的嵌套JSON结构。不过MySQL 5.7及以上版本自带的JSON函数刚好能完美解决这个需求!
最终可用的SQL语句
SELECT JSON_ARRAYAGG( JSON_OBJECT( 'event_name', e.event_name, 'user_Details', user_list ) ) AS nested_result FROM events e LEFT JOIN ( -- 先聚合每个事件对应的用户JSON数组 SELECT ers.event_id, JSON_ARRAYAGG( JSON_OBJECT( 'name', u.name, 'id', u.id ) ) AS user_list FROM event_request_sent ers INNER JOIN users u ON ers.user_id = u.id GROUP BY ers.event_id ) AS user_groups ON e.id = user_groups.event_id;
语句分步解释
- 子查询
user_groups:先把event_request_sent和users表关联,通过GROUP BY event_id把同一事件下的用户信息聚合成JSON数组——用JSON_OBJECT把单个用户的id和name包装成JSON对象,再用JSON_ARRAYAGG把这些对象拼成数组。 - 主查询组装最终结构:将
events表和子查询结果关联,用JSON_OBJECT把事件名称和对应的用户数组组装成单个事件的JSON对象,最后用JSON_ARRAYAGG把所有事件对象打包成顶层的JSON数组。
执行后得到的结果
这条语句会直接返回你期望的嵌套JSON格式:
[{ "event_name": "E1", "user_Details": [{ "name": "A", "id": 1 }, { "name": "B", "id": 2 }] }, { "event_name": "E2", "user_Details": [{ "name": "A", "id": 1 }] }]
额外优化提示
如果存在没有用户申请的事件,LEFT JOIN会保留该事件记录,但user_Details会是NULL。如果想让这类事件的user_Details显示为空数组,可以把主查询里的user_list替换成COALESCE(user_list, JSON_ARRAY())。
内容的提问来源于stack exchange,提问作者Anil




