mysql - 如何使用 mysql 原生 json 函数生成嵌套的 json 对象?

标签 mysql json

仅使用 MySQL 5.7.12 版(手册中的第 13.16 节)中的 native JSON 函数(无 PHP 等)我正在尝试编写查询以从包含子对象的关系表生成 JSON 文档。给定以下示例:

CREATE TABLE `parent_table` (
   `id` int(11) NOT NULL,
   `desc` varchar(20) NOT NULL,
   PRIMARY KEY (`id`)
);
CREATE TABLE `child_table` (
   `id` int(11) NOT NULL,
   `parent_id` int(11) NOT NULL,
   `desc` varchar(20) NOT NULL,
   PRIMARY KEY (`id`,`parent_id`)
);
insert `parent_table` values (1,'parent row 1');
insert `child_table` values (1,1,'child row 1');
insert `child_table` values (2,1,'child row 2');

我正在尝试生成如下所示的 JSON 文档:

[{
    "id" : 1,
    "desc" : "parent row 1",
    "child_objects" : [{
            "id" : 1,
            "parent_id" : 1,
            "desc" : "child row 1"
        }, {
            "id" : 2,
            "parent_id" : 1,
            "desc" : "child row 2"
        }
    ]
}]

我是 MySQL 的新手,怀疑有一种 SQL 模式可以根据一对多关系生成嵌套的 JSON 对象,但我找不到它。

在 Microsoft SQL(我更熟悉)中,以下工作:

select 
 [p].[id]
,[p].[desc]
,(select * from [dbo].[child_table] where [parent_id] = [p].[id] for json auto) AS [child_objects]
from [dbo].[parent_table] [p]
for json path

我试图在 MySQL 中编写如下等价物:

select json_object(
 'id',p.id 
,'desc',p.`desc`
,'child_objects',(select json_object('id',id,'parent_id',parent_id,'desc',`desc`) 
                  from child_table where parent_id = p.id)
)
from parent_table p;

select json_object(
  'id',p.id 
 ,'desc',p.`desc`
 ,'child_objects',json_array((select json_object('id',id,'parent_id',parent_id,'desc',`desc`) 
                              from child_table where parent_id = p.id))
 )
 from parent_table p

两次尝试均失败并出现以下错误:

Error Code: 1242. Subquery returns more than 1 row

最佳答案

您收到这些错误的原因是父 json 对象不期望将结果集作为其输入之一,您需要简单的对象对,例如 {name, string} 等 bug report - may be available in future functionality ...这只是意味着您需要将多行结果转换为以逗号分隔的结果串联,然后转换为 json 数组。

你的第二个例子几乎成功了。

您可以使用 GROUP_CONCAT 函数实现您想要的

select json_object(
  'id',p.id 
 ,'desc',p.`desc`
 ,'child_objects',json_array(
                     (select GROUP_CONCAT(
                                 json_object('id',id,'parent_id',parent_id,'desc',`desc`)
                             )   
                      from child_table 
                      where parent_id = p.id))
                   )
 from parent_table p;

这几乎可行,它最终将子查询视为一个字符串,并在其中留下转义字符。

'{\"id\": 1, 
\"desc\": \"parent row 1\", 
\"child_objects\": 
    [\"
    {\\\"id\\\": 1,
     \\\"desc\\\": \\\"child row 1\\\", 
    \\\"parent_id\\\": 1
    },
    {\\\"id\\\": 2, 
    \\\"desc\\\": \\\"child row 2\\\", 
    \\\"parent_id\\\": 1}\"
    ]
}'

为了使其以适当的格式工作,您需要更改创建 JSON 输出的方式,如下所示:

select json_object(
  'id',p.id 
 ,'desc',p.`desc`
 ,'child_objects',(select CAST(CONCAT('[',
                GROUP_CONCAT(
                  JSON_OBJECT(
                    'id',id,'parent_id',parent_id,'desc',`desc`)),
                ']')
         AS JSON) from child_table where parent_id = p.id)

 ) from parent_table p;

这将为您提供所需的确切结果:

'{\"id\": 1, 
\"desc\": \"parent row 1\", 
\"child_objects\": 
    [{\"id\": 1, 
    \"desc\": \"child row 1\", 
    \"parent_id\": 1
    }, 
    {\"id\": 2, 
    \"desc\": \"child row 2\", 
    \"parent_id\": 1
    }]  
}'

关于mysql - 如何使用 mysql 原生 json 函数生成嵌套的 json 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37470949/

相关文章:

python - 获取executemany后插入的主键

php - 在 PHP 中使用另一个类中的 MySQLi

mysql - 在连接表上搜索全名

java - 使用 gson 解析 JSON 对象数组

python - 将深度嵌套的 JSON 响应从 API 调用转换为 pandas 数据帧

javascript - 如何在 AngularJS 中编写通用排序

r - 将不等长列表的列表转换为数据帧

json - 如何使用Sencha Touch数据模型读取嵌套的JSON结构?

php - mysql中的数据顺序,在php中按顺序显示

php - 这个问题应该如何设计数据库结构呢?