在MySQL 5.7.12版本(手册中的第13.16节)中仅使用本机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
答案 0 :(得分:11)
你得到这些错误的原因是父json对象不期望结果集作为其输入之一,你需要有简单的对象对,如{name,string}等bug report - may be available in future functionality ...这只是意味着您需要将多行结果转换为用逗号分隔的结果的连接,然后转换为json数组。
你的第二个例子差不多了。
使用GROUP_CONCAT功能
可以实现目标ContainerRequestFilter
这几乎可以工作,它最终将子查询视为一个字符串,在那里留下转义字符。
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;
为了使其以适当的格式工作,您需要更改创建JSON输出的方式,如下所示:
'{\"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}\"
]
}'
这将为您提供所需的确切结果:
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;
答案 1 :(得分:1)
对于MariaDb,CAST AS JSON不起作用。但是JSON_EXTRACT可以用于将字符串转换为JSON对象:
select json_object(
'id',p.id
,'desc',p.`desc`
,'child_objects',JSON_EXTRACT(IFNULL((select
CONCAT('[',GROUP_CONCAT(
json_object('id',id,'parent_id',parent_id,'desc',`desc`)
),']')
from child_table where parent_id = p.id),'[]'),'$')
) from parent_table p;