[英]How would I join two tables in MySQL (many to one) and get a specific JSON output (as shown below)
我将如何加入MySQL中的两个表(多对一)并获得特定的JSON output(如下图)
注意:请不要将其标记为重复
之前发布的一个问题与此非常相似,但在几点上并不相同。
这不是我要找的,这个问题与此不同: Mysql concat 和 group_concat
我在这篇文章的底部放了一个更长的描述和更多的细节,为什么不应该将其标记为重复,以及它有何不同。
要求:
output JSON 将是一个数组(teams),数组(struct)的每个元素都将包含一个数组(persons)。
顶级数组属于父表“teams”(JSON 数组的每个元素包含单行数据),嵌套数组属于子表“persons”,它与父表具有多对一关系。
如果一个简单的 select 仅从一张表完成: select * from <child_table>;
我得到了父表的 id(主键),但是在 JSON 结果中,除了父主键,我还想显示父表的另一个字段(父表中的字段值,而不仅仅是行 id / 键,这对 JSON 输出没有帮助)。
此处提供: .sql 文件以创建数据库、架构、插入数据(以测试解决方案)
create schema if not exists test;
use test;
create table if not exists team
(
id int unsigned auto_increment primary key,
team_name varchar(30) unique not null,
description text
);
use test;
create table if not exists person
(
id int unsigned auto_increment primary key,
id_team int unsigned not null,
person_name varchar(40) not null,
notes varchar(40) not null,
constraint team_person unique (id, id_team),
foreign key (id_team) references team (id)
);
-- insert teams (2)
use test;
insert into team(team_name)
values ('team1');
insert into team(team_name)
values ('team2');
insert into team(team_name)
values ('team3');
-- insert persons (x2 per team = 4)
use test;
insert into person(id_team, person_name)
values ((select id from team where team_name = 'team1'),
'john');
insert into person(id_team, person_name)
values ((select id from team where team_name = 'team1'),
'tom');
insert into person(id_team, person_name)
values ((select id from team where team_name = 'team1'),
'marie');
-- team 2
insert into person(id_team, person_name)
values ((select id from team where team_name = 'team2'),
'scott');
insert into person(id_team, person_name)
values ((select id from team where team_name = 'team2'),
'mark');
我需要 output JSON 看起来像这样(完全展开 - 两个 arrays 具有来自两个表的值):
您在这里看到的是一组团队,“团队”表中每行一个 JSON 元素。
在每个元素中,一组人,每行一个 JSON 元素,来自“人”表,代表多对一关系。
{
"team_persons": [
{
"team": "team1",
"id_team": 1,
"persons": [
{
"id_person": 1,
"personaName": "john"
},
{
"id_person": 2,
"personaName": "allison"
}
]
},
{
"team": "team2",
"id_team": 2,
"persons": [
{
"id_person": 3,
"personaName": "katrina"
},
{
"id_person": 4,
"personaName": "scott"
}
]
}
]
}
output中可以看到,JSON output中的每条记录中都显示了父表字段: id_team & team_name 。
JSON中有两个arrays:
我知道SELECT JSON_OBJECT / JSON_ARRAYAGG会涉及。 我不确定如何在两个表的 SQL 连接中同时使用两者,以实现所需的自定义 JSON output。
SQL 中的两个表的连接如下所示:
select t.id id_team, p.id id_person, p.person_name, t.team_name
from team t,
person p
where t.id = p.id_team;
谢谢你!
请不要将其标记为重复,它不是:
我只处理两个表,其中 JSON output 需要从一个非常顶级的数组开始(与其他帖子不同)。
{
"team_persons": [
引用的帖子和方法存在问题:
有一种更好、更现代的方法可以使用其他内置 MySQL 函数来执行此操作。
请不要关闭这个问题。 要求非常不同。
我需要一种使用的方法: JSON_OBJECT / JSON_ARRAYAGG and NOT CONCAT and NOT GROUP_CONCAT 。 并且也仅在两个非常简单的表上。
问问题时,如果试图解决的最简单(不准确)的事情能帮助其他人 map 他们的问题就成了问题。 在下面的问题中,我去除了所有复杂性以提供一个简单示例。
我希望提供一个更容易理解的问题,其他人可能会从中受益(使用复制表结构的代码),以及一个更精致的答案,因为我相信给出的答案对于更简单的用例来说可以变得更简单,并且更容易理解。
SELECT
JSON_PRETTY(
JSON_OBJECT(
'team_persons', JSON_ARRAYAGG(
JSON_OBJECT(
'team', team,
'id_team', id_team,
'persons', persons
)
)
)
) AS _result
FROM (
SELECT
t.id AS id_team,
t.team_name AS team,
JSON_ARRAYAGG(
JSON_OBJECT(
'id_person', p.id,
'personName', p.person_name
)
) AS persons
FROM team t JOIN person p ON t.id = p.id_team
GROUP BY id_team
) AS p;
在 MySQL 8.0.28 上测试过,但它也应该适用于 MySQL 5.7.22(或更高版本)。
包括空队是棘手的。 一开始只能使用 LEFT OUTER JOIN,但随后它会抱怨,除非我将 GROUP BY 更改为引用基列,而不是别名:
...
FROM team t LEFT OUTER JOIN person p ON t.id = p.id_team
GROUP BY t.id
但是,这可能不会产生您想要的结果,我假设它是一个空的 JSON 数组。 因为外部联接的结果确实有一行,但是带有 NULL,所以您会得到一个带有 NULL 的假团队成员:
{
"team": "team3",
"id_team": 3,
"persons": [
{
"id_person": null,
"personName": null
}
]
}
一种解决方法是将当前查询与 JOIN 与另一个排除连接查询联合起来:
SELECT
JSON_PRETTY(
JSON_OBJECT(
'team_persons', JSON_ARRAYAGG(
JSON_OBJECT(
'team', team,
'id_team', id_team,
'persons', persons
)
)
)
) AS _result
FROM (
SELECT
t.id AS id_team,
t.team_name AS team,
JSON_ARRAYAGG(
JSON_OBJECT(
'id_person', p.id,
'personName', p.person_name
)
) AS persons
FROM team t JOIN person p ON t.id = p.id_team
GROUP BY t.id
UNION
SELECT
t.id,
t.team_name,
JSON_ARRAY()
FROM team t LEFT OUTER JOIN person p ON t.id = p.id_team
WHERE p.id_team IS NULL
) AS p;
UNION 的后半部分返回一个文字空数组,因为反正团队中没有人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.